2026-09-20
lock_flag.c
#include <stdio.h>
#define FLAG_A 1
#define FLAG_B 2
#define FLAG_LOCKED (1 << 31)
int main(void) {
int flags = FLAG_A | FLAG_LOCKED;
printf("%d\n", flags);
}
FLAG_LOCKEDを最上位ビット(31ビット目)に立てるつもりですが、このコードには問題があります。何が問題で、どう直せばよいでしょうか?
Answer
1 << 31の1は(接尾辞を付けていないので)符号付きのintです。32ビットのintで1を31ビット左シフトすると、結果の2147483648はintの最大値(2147483647)を超えて表現できず、符号付き整数オーバーフローという未定義動作になります。フラグ用の定数を素朴に1 << nで書いていくと、nが31に達した瞬間だけこの問題が起こるので、他のビットでは何の問題もなく動いていたコードが最上位ビットだけで壊れるという、気づきにくい形の罠です。符号なしのunsignedを使えば、31ビット目は単に値の一部であり、オーバーフローという概念自体が(定義された)モジュロ演算に置き換わるので問題は起こりません。リテラルにu接尾辞を付け、変数の型もunsignedに直します:
#include <stdio.h>
#define FLAG_A 1u
#define FLAG_B 2u
#define FLAG_LOCKED (1u << 31)
int main(void) {
unsigned flags = FLAG_A | FLAG_LOCKED;
printf("%u\n", flags);
}