【C言語】
全角文字が1文字2バイトとは限らない

警告:printf(“%zu\n”,strlen(“全角”))の結果は?


■EUC,Shift_JIS,UTF-8で結果が違う

#include <stdio.h>
#include <string.h>
//strlen("全角")は4とは限らない
void f1(void){
    printf("4を期待してはいけない:strlen = %zu\n",strlen("全角"));
    printf("5を期待してはいけない:sizeof = %zu\n",sizeof("全角"));
}
//全角を2byteと決めつけるのは危険
void f2(void){
    for(size_t i = 0;i < sizeof("全");i++){
        printf("%02x[%zu]\n",(unsigned char)"全"[i],i);
    }
}
//昔は問題がなかったがUTF-8では事故になる例
void f3(void){
    char    src[3] = "全";//右辺が3byteの場合終端文字が入らない
    char    dst[3];
    strcpy(dst,src);    //終端文字がないので暴走の可能性
    printf("%s\n",dst); //終端文字がないので暴走の可能性
}
int main(void){
    f1();
    f2();
    fflush(stdout);
    f3();
}


■ソースコードがEUCの場合

4を期待してはいけない:strlen = 4
5を期待してはいけない:sizeof = 5
c1[0]
b4[1]
00[2]
全

プログラマの期待した結果になります。


■ソースコードがShift_JISの場合

4を期待してはいけない:strlen = 4
5を期待してはいけない:sizeof = 5
91[0]
53[1]
00[2]
全

プログラマの期待した結果にこの例ではなりましたが、

gcc/clangでShift_JISのソースコードをコンパイルすると
5C問題(いわゆる化け字問題)を起こすので

基本的に
gcc/clangでShift_JISのソースコードをコンパイル
してはいけません。


■ソースコードがUTF-8の場合

4を期待してはいけない:strlen = 6
5を期待してはいけない:sizeof = 7
e5[0]
85[1]
a8[2]
00[3]
====中略
==755==ERROR: AddressSanitizer: stack-buffer-overflow on address

プログラマの期待した結果になりません
実験した環境下ではプログラムは異常終了しました。


■実験用スクリプト

rm -f ./a.out
nkf -we -Lu f0.c > EUC.c
nkf -g EUC.c
gcc EUC.c -Wall -Wextra -fsanitize=address
./a.out | nkf

rm -f ./a.out
iconv -f utf8 -t sjis f0.c > Shift_JIS.c
nkf -g Shift_JIS.c
gcc Shift_JIS.c -Wall -Wextra -fsanitize=address
./a.out |nkf 

rm -f ./a.out
cp f0.c UTF-8.c
nkf -g UTF-8.c
gcc UTF-8.c -Wall -Wextra -fsanitize=address
./a.out