시프트 연산자는 변수의 비트를 왼쪽 또는 오른쪽으로 원하는 자릿수만큼 이동시켜주는 연산자이다.
이동된 칸은 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바이트이다.
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] - 아두이노 - 비트 마스크, bit mask
[arduino] - 아두이노 - 도트 매트릭스 제어하기, dot matrix
'Arduino' 카테고리의 다른 글
아두이노 IDE 환경 설정하기 - preferences.txt 설정, 에디터 폰트 변경(추천) (0) | 2019.10.31 |
---|---|
ESP8266 / ESP32 - time.h 라이브러리 이용 시간 출력 및 NTP 서버 시간 동기화 하기 (0) | 2019.10.28 |
아두이노 - 도트 매트릭스 제어하기, dot matrix (0) | 2019.10.22 |
아두이노 - 비트 마스크, bit mask (0) | 2019.10.19 |
아두이노 - 비트 연산자 (0) | 2019.10.16 |
아두이노 우노와 NodeMcu의 성능 비교, MCU 속도 벤치 마크 (0) | 2019.10.16 |
아두이노 - 배열 값 shuffle, 배열의 값을 무작위 순서대로 섞는 방법 (0) | 2019.10.07 |
아두이노 - random() 함수 사용하기, 랜덤함수 (0) | 2019.10.06 |