プログラミング言語C/C++のchar型が、符号あり/符号なしのいずれかは処理系定義(implementation defined)*1。各コンパイラでの実装についてメモ。
まとめ:
char型を「符号あり(signed)」と仮定しないこと。(とはいえ、この仮定をおくコードは多い…)- 特にARMアーキテクチャ(近年ではAndroid NDK)では既定で
char型=「符号なし」 となることに注意。
gcc
gccでの既定動作は “ターゲットアーキテクチャ依存”*2となる。-fsigned-char/-funsigned-charオプション*3 にて「符号あり」/「符号なし」を明示指定可能。
当てにならないメモ:符号あり=MIPS, SPARC、符号なし=PowerPC
2026-02-10追記:ターゲットの gcc/config/*.h ヘッダでDEFAULT_SIGNED_CHARマクロ定義を確認するのが確実。
Clang
Clangの既定動作は不明(少なくともx86, x86_64では符号あり。gccと同一?)明示指定オプションはgccと同じ。
2026-02-10追記:LangOptions::CharIsSignedビットフラグで制御される。Clangデフォルト値は1(符号あり)?LLDBデバッガではArchSpec::CharIsSignedByDefault()で動的判断している模様。
*1:C/C++の言語仕様上 char, signed char, unsigned char の3つは異なる型として扱われる。
*2:より正確には“ABI(Application Binary Interface)依存”。http://gcc.gnu.org/onlinedocs/gcc/Characters-implementation.html参照
*3:または否定形-fno-unsigned-char/-fno-signed-charオプションでも指定可。
*4:Porting low-level x86 optimized code to the ARM Cortex-A8 architecture - Stack Overflowの回答によれば、最近までARMには “符号ありを扱う高速な命令が存在しなかった” ため、伝統的に「符号なし」が既定動作とのこと。