😎

C言語でSJISを使用してはいけない理由

2023/01/12に公開

この記事では,SJISでコーディングすることのデメリットを説明しています.

なぜダメなのか

問題のコードとエラー

例としてこのようなコードがあるとしましょう.(SJIS)

hello_wowrld.c
#include <stdio.h>

int main(void){
    // 数字表
    int num[3]={1,2,3};
    
    printf("%d\n",num[0]);
    // 与えられた変数と文字列を表示する機能
    printf("%d\n", num[0]);
	
    return 0;
}

これを実行すると,こんなエラーが出ます.

$ gcc hello_world.c -w -o hello
hello_world.c: In function ‘main’:
hello_world.c:7:19: error: ‘num’ undeclared (first use in this function)
    7 |     printf("%d\n",num[0]);
      |                   ^~~
hello_world.c:7:19: note: each undeclared identifier is reported only once for each function it appears in

原因

さて,numは宣言されているのに,されていないことになっていますね.
理由は直前にあるコメントです.
のSJISコードは149 92で,この92はSJISで\となります.
\は,その次の行は、この行の続きである という意味を示します.
そのため,

// 数字表
int num[3]={1,2,3};

は,(アバウトに表現するならば)

// 数字表 int num[3]={1,2,3};

として,解釈されます.
だからnumが宣言されていないこととなるのです.
では,このコメントを消去して実行してみましょう.

問題のコードとエラー part2

コメントを消去したプログラムはこうなりますね.

hello_wowrld.c
#include <stdio.h>

int main(void){
    int num[3]={1,2,3};
    
    printf("%d\n",num[0]);
    // 与えられた変数と文字列を表示する機能
    printf("%d\n", num[0]);
	
    return 0;
}

実行結果はこんな感じ

$ gcc hello_world.c -w -o hello

$ ./hello
1

これを実行すると,エラーは出ないものの,2回表示されませんね.
原因は,やはりコメントにあります.
のSJISコードは149 92で,この92はSJISで\となります.
\は,先ほども申し上げた通り,その次の行は、この行の続きである という意味を示します.
つまり解釈としては,(アバウトに表現すると)

// 与えられた変数と文字列を表示する機能 printf("%d\n", num[0]);

となってしまうため,エラーではないものの,想定した挙動をしてくれないわけです.
では,このコメントを消去してもう一度実行してみましょう.

対策

hello_wowrld.c
#include <stdio.h>

int main(void){
    int num[3]={1,2,3};
    
    printf("%d\n",num[0]);
    // 与えられた変数と文字列を表示する機能
    printf("%d\n", num[0]);
	
    return 0;
}

ようやく想定した挙動をしましたね!
このように,SJISだとコメントのせいでエラーが出たり,想定している挙動をしなかったりするわけです.
今回紹介した表や能以外にも,噂 十 申 などがあります.(これらを総じてダメ文字とか言ったりします)
対策として,以下のような方法があります.

  1. UTF-8等を使用する(著者推奨)
  2. コメントの最後に「.」を必ず追加する
  3. gccのオプションに--input-charset=cp932を追加する(UTF-8として読み込ませる)

Plus

たまにプログラマー界隈で聞く
//このコメントを書いたらなんかうまくいった
っていうのは,これが原因ですね.

Discussion