トップ «前の日記(2016-09-18) 最新 次の日記(2016-09-25)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2016-09-19

_ Visual StudioでclangでC11を試す(が)

C11のAppendix Kを試してみたくて、bash on Windowsのclangで次のコードをコンパイルした。

#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
int main()
{
    char tmp[80];
    int n = scanf_s("%s", tmp); // => コンパイルエラーとなる
    if (n > 0) {
        puts(tmp);
    }
}

するとscanf_sは未定義だと警告され、結局はリンクエラーとなる。

test.c:(.text+0x1e): `scanf_s' に対する定義されていない参照です

/usr/include/studio.hを見たら、確かに定義が存在しない。

まあAppendix Kはオプションだからそんなものかも知れない。

でも待て、Visual Studio 2015 - Clang with Microsoft CodeGenなら行けるのではないか? と考えた。

というのは、clang with MS CodeGenでclang用に追加されるincludeディレクトリはC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ClangC2\includeで、ここにはstdio.hは存在しないからだ。

つまり、stdio.hはVC++のヘッダを共通で利用することになる。

で、コンパイルすると、無事コンパイルが成功する。

……いや、コンパイルが成功するのは期待する動作ではない。

期待する動作は、VC++がそうするようにコンパイルエラーとなることだ。

VC++は上記のソースをコンパイルすると次のエラーを吐く。

test.c
test.c(8): warning C4473: 'scanf_s': 書式文字列として渡された引数が不足しています
test.c(8): note: プレースホルダーとそのパラメーターには 2 の可変個引数が必要ですが、1 が指定されています。
test.c(8): note: 不足している可変個引数 2 が書式文字列 '%s' に必要です
test.c(8): note: この引数はバッファー サイズとして使用されます

で、予想されるように、clangでコンパイルしたプログラムは実行できて、かつ動作は予想できない。バッファサイズを与えていないから何文字入力できるか不明だし、とりあえず山ほど入力すれば0xC0000005で死ぬ。

これはちょっとひどいのではないか? まだ、scanf_sは未定義といって怒るほうが1000億倍ましだ。

もちろん以下のように書き直すと、期待通りに動作する。

#define __STDC_WANT_LIB_EXT1__ 1  // <= これ結局本当におまじない以上の意味が無いということだな
#include <stdio.h>
int main()
{
    char tmp[80];
    int n = scanf_s("%s", tmp, (unsigned)sizeof(tmp)); // x64でも通るようにするには(unsigned)キャストが必要(size_tではない)
    if (n > 0) {
        puts(tmp);
    }
}


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|

ジェズイットを見習え