임베디드 용어 사전
기초·메모리

시프트

비트를 좌우로 밀어 옮기는 연산. 이동량과 타입을 잘못 잡으면 미정의 동작이 되거나 부호가 번진다.

마스크를 만들고 필드를 배치하는 기본 도구인데, C 표준이 정하지 않은 구석이 많다.

데는 곳 셋

1 << 31          /* 1 은 int(부호 있음) → 부호 비트를 침범, 미정의 동작 */
1u << 31         /* 이렇게 쓴다 */

uint32_t v; v << 32;     /* 타입 폭 이상 시프트 = 미정의. 0 이 되리라 기대하면 안 된다 */

int8_t x = -8; x >> 1;   /* 음수의 오른쪽 시프트는 구현 정의(대개 산술 시프트) */

세 경우 모두 컴파일은 되고, 어떤 툴체인에서는 의도대로 돌아간다. 그래서 더 위험하다.

실무 규칙

상수에 u 를 붙인다              1u << n
이동량이 타입 폭보다 작은지 확인    n < 32
부호 있는 값은 시프트하지 않는다    나눗셈이 의도라면 / 를 쓴다
넓은 타입으로 먼저 승격한다        ((uint32_t)a << 16) | b

곱셈·나눗셈 대용은 이제 불필요하다

옛 코드에 x >> 1 로 2로 나누는 관용구가 많지만, 요즘 컴파일러는 / 2 를 알아서 시프트로 바꾼다. 의도를 그대로 쓰는 편이 읽기 쉽고 부호 함정도 피한다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 비트 조작 — 레지스터를 정확히 건드리는 법