次のページ 前のページ 目次へ

6. char 型

さて,ここらから ARM toolchain 特有の話題に入ります.

ARM gcc では,char 型で宣言した変数は unsinged char として扱われます. x86 などの他の gcc では signed char として扱われます. 普通はこちらの方ですね.

char が符号あり・なし,ということ自体は C の規約では「実装依存」 であるため,C としては間違っていません. が,世の中のほとんどの C プログラムは char が符号つきであるという 前提で書かれていますし,読者の認識もそうだと思います.

というわけで,既存の C のプログラムをコンパイルして使用しようとする場 合,これが問題となる場合があります.

6.1

以下のようなプログラムをコンパイルし,実行してみます.


#include <stdio.h>

main ( void )
{
        char c1 = 0xff, c2 = 0x01;
        
        if ( c1 > c2 ) {
                printf ( "c1 > c2\n" );
        } else {
                printf ( "c1 <= c2\n" );
        }
}

x86 では signed char として扱われるので,c1 = -1, c2 = 1 で, 実行結果は

$ ./a.out 
c1 <= c2
となりますが,ARM では unsigned char として扱われるので c1 = 255, c2 = 1 となり,実行結果は
$ ./a.out 
c1 > c2
となります.

6.2 由緒正しい対策

char 型変数を符号つきの文脈で使用する場合は,明示的に signed char と宣言することでこの問題を解決することができます.

もちろん,C として移植性をまじめに考えるとこのようにプログラムすべきなのですが…  慣習としてはちょっと受け入れがたいものがあるかもしれません.

6.3 バッドノウハウな対策

ARM gcc のコンパイルオプションで -fsigned-char と指定することで, char 型を signed char と扱わせることができます.

もちろん,先のプログラムでも以下のように x86 と同様の結果が得られます.

$ gcc -fsigned-char char.c 
$ ./a.out 
c1 <= c2


次のページ 前のページ 目次へ