🗃️

clを使ってコンパイルしたらバグが起きた(いつもの)

2025/02/17に公開

問題

さて、問題です。こちらのコードを御覧ください。

#include <stdio.h>
int main(void){
    int a[5] = {1,2,3,4,5};
    int *p;
    p = &a[0];

    printf("配列\n");
    for(int i = 0;i < 5;i++){
        printf("%d : %d\n",i,a[i]);
    }
    printf("ポインタ 配列\n");
    for(int i = 0;i < 5;i++){
        printf("%d : %d\n",i,p[i]);
    }
    printf("ポインタ 加算\n");
    for(int i = 0;i < 5;i++){
        printf("%d : %d\n",i,*(p+i));
    }
    printf("ポインタ 奇怪\n");
    for(int i = 0;i < 5;i++){
        printf("%d : %d\n",i,i[p]);
    }
}

ぜんぶ配列にある数字を出していくfor文ですね。
どんなバグが起きるでしょーか?

出力結果

こちら、実行結果でーす。文字化けは気にしないでください。

驟榊・
0 : 1
1 : 2
2 : 3
3 : 4
4 : 5
繝昴う繝ウ繧ソ縲驟榊・
0 : 1
1 : 2
2 : 3
3 : 4
4 : 5
繝昴う繝ウ繧ソ縲蜉邂予n0 : 1
1 : 2
2 : 3
3 : 4
4 : 5
繝昴う繝ウ繧ソ縲螂・ェ
0 : 1
1 : 2
2 : 3
3 : 4
4 : 5

一見するとおかしくないですね。ええ、一見するとね。

繝昴う繝ウ繧ソ縲蜉邂予n0 : 1
1 : 2
2 : 3
3 : 4
4 : 5

なんで改行されないんですかね?

答え

C言語をコンパイルする人なら分かるでしょうが、UTF-8のソースコードをデフォルトのShift-JISでコンパイルしました。

.\pointer.c(15): warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含
んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。

いつもの文字コードによる問題ですね。
そのため、UTF-8でコンパイルするようにします。

cl /source-charset:utf-8 .\pointer.c

そうすると期待通りの結果が得られます。

配列
0 : 1
1 : 2
2 : 3
3 : 4
4 : 5
ポインタ 配列
0 : 1
1 : 2
2 : 3
3 : 4
4 : 5
ポインタ 加算
0 : 1
1 : 2
2 : 3
3 : 4
4 : 5
ポインタ 奇怪
0 : 1
1 : 2
2 : 3
3 : 4
4 : 5

Shift-JISを使わないようにしよう!

毎度ながらいつものことですが、Shift-JISを使うよりUTF-8でコンパイルできるようにするのがいいです。
https://qiita.com/takey/items/ca49c8048992e8f6c674
https://zenn.dev/tukurugi_v/articles/1b0058db5203ae
Powershell 7を使っているなら全人類はprofileにこれを書き足して楽したほうがいいと思っています。

Microsoft.PowerShell_profile.ps1
function cl {& cl.exe /source-charset:utf-8 @args}

いないとは思いますが、念のためPathがない人向けです。

Microsoft.PowerShell_profile.ps1
function cl {& "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\bin\Hostx64\x64\cl.exe" /source-charset:utf-8 @args}

cl.exeのところをclにすると無限ループが起きるのか動作が停止します。
Visual Studio 2015以前のならBOM付きUTF-8での保存にはなりますが・・・それでもエラーの原因を減らせるなら容易いと思いませんか?

以上、いつものくだらないバグでした。

Discussion