bit shift 질문입니다

아두이노에서 bit shift를 해야 할 일이 생겼습니다
개발 환경은 아두이노 IDE(정확히는 visual micro) 사용중입니다.

uint8_t note2char(uint8_t note) // 미디의 note를 줄과 fret 번호로 나타냄
{
	uint8_t ret = 0;
	ret |= ((note - 4) / 5) << 4;
	ret |= (1 << (((note - 4) % 5) - 1)) & 0x0f;
	
	return ret;
}

솔레노이드에 I/O 레지스터를 대응시켜 작동시킬 생각인데요…
만약 4가 들어올 경우, 하위 4비트는 0이 되어야 합니다.
note로 4가 들어오면

4 - 4   =  0
0 % 5   =  0
0 - 1   = -1
1 << -1 =  0

가 되어야 하는데…
자꾸 1이 나옵니다.

그래서 실험을 해봤습니다.

Serial.print("0x04 >>  1 = "); Serial.println(0x04 >>  1, HEX);
Serial.print("0x04 >> -1 = "); Serial.println(0x04 >> -1, HEX);
Serial.print("0x01 >>  1 = "); Serial.println(0x01 >>  1, HEX);
Serial.print("0x01 >> -1 = "); Serial.println(0x01 >> -1, HEX);
Serial.print("0x00 >>  1 = "); Serial.println(0x00 >>  1, HEX);
Serial.print("0x00 >> -1 = "); Serial.println(0x00 >> -1, HEX);

이렇게요.
결과는

0x04 >>  1 = 2
0x04 >> -1 = 8
0x01 >>  1 = 0
0x01 >> -1 = 2
0x00 >>  1 = 0
0x00 >> -1 = 0

이런식으로 ‘음수만큼 시프트’ 잘 됩니다.
상수일 경우만 음수로 시프트가 가능한 걸까요?

C/C++ 의 bitwise shift 는 음수 counter 에 대해 UB ( undefined behavior ) 입니다.
컴파일러마다 동작이 다르거나, 지원하지 않습니다.

4 Likes

앗…글쿤요
if로 분기를 줄 수 밖에 없겠네요
분기 최대한 줄여볼려고 하는데 허허…

이런 문제는 분기가 필요없죠 다시한번 생각해보세요.

시프트 연산자의 피연산자를 counter라 하는군요
위 내용으로 계속 검색했는데 안나오더니 negative counter라고 치니깐 바로 뜨네요
하나 알아갑니당

해결했습니다

uint8_t note2char(uint8_t note) // 미디의 note를 줄과 fret 번호로 나타냄
{
	uint8_t ret = 0;
	uint8_t temp = note - 4;
	ret |= (temp / 5) << 4;
	ret |= ((temp % 5 > 0) << ((temp % 5) - 1)) & 0x0f;
	return ret;
}

이런식으로 하니깐 되네요 감사합니다

음수 시프트를 활용하지 않고 해야 할것 같은데…일단은 이런식으로 했습니다

1 Like