Namaran

Code daily. Without assist.

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 << 311は(接尾辞を付けていないので)符号付きのintです。32ビットのint1を31ビット左シフトすると、結果の2147483648intの最大値(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);
}