반응형

시프트 연산자는 변수의 비트를 왼쪽 또는 오른쪽으로 원하는 자릿수만큼 이동시켜주는 연산자이다.

이동된 칸은 0으로 채우고 변수의 자료형 크기를 벗어나는 비트 값은 사라진다. 

 

비트를 왼쪽으로 옮김 : 코드상 표기 "변수 << 변수의 비트 이동수 "

비트를 오른쪽으로 옮김 : 코드상 표기 "변수 >> 변수의 비트 이동수 "
비트를 왼쪽으로 옮긴 후 할당: 코드상 표기 "변수 <<= 변수의 비트 이동수 "

비트를 오른쪽으로 옮긴 후 할당: 코드상 표기 "변수 >>= 변수의 비트 이동수 "

사용 예

uint8_t num1 =  5; // 자료형이 양수 8비트인 숫자 5 = 0000 0101
uint8_t num2 =  2; // 자료형이 양수 8비트인 숫자 2 = 0000 0010
uint8_t value;        // 자료형이 양수 8비트인 변수 선언

value = num1 << 3;  // 0000 0101 -> 0010 1000 = 40
value = num1 >> 2;  // 0000 0101 -> 0000 0001 = 1, 이동 후 자료형의 크기를 벗어난 비트 01은 사라짐 
num1 <<= 3;          // 0000 0101 -> 0010 1000 = 40
num1 >>= 2;          // 0000 0101 -> 0000 0001 = 1, 이동 후 자료형의 크기를 벗어난 비트 01은 사라짐 

 

시프트 연산자를 이용하여 왼쪽으로 한 자리씩 이동하게 되면 "이전 자릿수의 값 x 2"가 된다. 

곱셉을 대체할 수 있다. 

 

uint8_t num1 = 1;

value = num1 << 1; // 0000 0010: 2 

value = num1 << 2; // 0000 0100: 2 x 2 = 4       (또는 22)

value = num1 << 3; // 0000 1000: 4 x 2 = 8       (또는 23)

value = num1 << 4; // 0001 0000: 8 x 2 = 16     (또는 24)

value = num1 << 5; // 0010 0000: 16 x 2 = 32    (또는 25)

value = num1 << 6; // 0100 0000: 32 x 2 = 64    (또는 26)

value = num1 << 7; // 1000 0000: 64 x 2 = 128  (또는 27)

 

짝수일 경우(가장 오른쪽 비트가 0)  오른쪽으로 한 자리씩 이동하게 되면 "이전 자릿수의 값 / 2"가 된다. 

나눗셈을 대체할 수 있다. 

* 홀수일 경우(가장 오른쪽이 1)에는 1이 삭제되어 나누어지는 게 아니라 숫자가 변경된다.

또한, 가장 왼쪽의 비트가 1일 때 변수의 자료형이 음수를 포함한 경우에는 오른쪽으로 비트 이동시 이동된 자리에는 1이 채워지고 자료형이 음수를 포함하지 않는 경우에는 이동된 자리에는 0이 채워진다.

 

char temp = 131 >> 1; // 1000 0011 -> 1100 0001 

unsigned char temp = 131 >> 1; // 1000 0011 -> 0100 0001 

 

자료형 char은 음수를 포함한 8비트 자료형이다. 8비트 MCU인 아두이노에서는 아래와 같이 char 변수에 131을 입력하고 오른쪽으로 이동시키면 1100 0001(193 또는 -63)이 되는데 32비트 MCU인 ESP32에서 이동시키게 되면 자료형 char의 사이즈가 1바이트로 인식됨에도 불구하고 0100 0001(65)이 되게 된다. 

 

아두이노 char temp = 131 >> 1; // 1000 0011 -> 1100 0001 

ESP32    char temp = 131 >> 1; // 1000 0011 -> 0100 0001, 같은 코드이지만 MCU가 변경되면 결괏값이 바뀔 수 있다.

 

 

추측하건대, ESP32의 자료형 char가 sizeof() 함수를 이용했을 때 1바이트로 인식되나 실제로는 1바이트 이상의 크기일 경우(예, 0000 0000 1100 0001)처럼 연산된다고 볼 수 있다. 이렇게 MCU에 따라 결과가 달라지게 되면 혼란이 발생하게 된다. 이런 혼란을 방지하기 위해 자료형으로 int8_t 또는 uint8_t의 형식을 사용하여 명확하게 음수를 포함하는지 여부와 더불어 비트의 크기를 정해주어야 의도치 않는 결과를 방지할 수 있다.  

 

아두이노 int8_t temp = 131 >> 1; // 1000 0011 -> 1100 0001

ESP32    int8_t temp = 131 >> 1; // 1000 0011 -> 1100 0001 

아두이노 uint8_t temp = 131 >> 1; // 1000 0011 -> 0100 0001

ESP32    uint8_t temp = 131 >> 1; // 1000 0011 -> 0100 0001 

 

참고로 아두이노에서의 자료형 int의 크기는 2바이트이지만, ESP32에서는 4바이트이다.  

ar_bit.ino
0.00MB
void setup() {
  Serial.begin(9600);
  char temp1 =  131;               // 자료형 char는 음수를 포함하지만 
  Serial.println(temp1);           // 시리얼 모니터에서 음수를 정상적으로 표시할 수 없다.
  unsigned char print_val = temp1; // -> ASCII 코드에 표시할 문자가 없다.
  Serial.println(print_val);       // 음수를 표시하기 위해 자료형을 양수로 변경 출력
  for (int i = 0; i < 8; i++) Serial.print(bitRead(temp1, 7-i)); // 1000 0011
  Serial.println();
  temp1 = temp1 >> 1;              // 1000 0011 -> 1100 0001 
  Serial.println(temp1);          
  print_val = temp1;
  Serial.println(print_val);       // 음수를 표시하기 위해 자료형을 양수로 변경
  for (int i = 0; i < 8; i++) Serial.print(bitRead(temp1, 7-i));
  Serial.println();
  unsigned char temp2 = 131;       // 자료형을 양수로 변경
  temp2 = temp2 >> 1;              // 1000 0011 -> 0100 0001 
  Serial.println(temp2);
  for (int i = 0; i < 8; i++) Serial.print(bitRead(temp2, 7-i));
  Serial.println();
  int8_t temp3 =  131;             // 음수를 포함하는 자료형 
  Serial.println(temp3);           // 자료형이 char가 아니므로 음수 출력 -125
  for (int i = 0; i < 8; i++) Serial.print(bitRead(temp3, 7-i)); // 1000 0011
  Serial.println();
  temp3 = temp3 >> 3;              // 1000 0011 -> 1100 0001 
  Serial.println(temp3);
  for (int i = 0; i < 8; i++) Serial.print(bitRead(temp3, 7-i));
  Serial.println();
  uint8_t temp4 = 131;             // 양수 8비트 자료형
  temp4 = temp4 >> 1;              // 1000 0011 -> 0100 0001 
  Serial.println(temp4);
  for (int i = 0; i < 8; i++) Serial.print(bitRead(temp4, 7-i));
  Serial.println();
}

void loop() {
}

 

관련 글

[arduino] - 아두이노 - 비트 연산자

[arduino] - 아두이노 - 비트 시프트 연산자

[arduino] - 아두이노 - 비트 마스크, bit mask

[arduino] - 아두이노 - 도트 매트릭스 제어하기, dot matrix

 

 

+ Recent posts