これが私の死んだ単純なダミーコードです:
#include <errno.h>
int main(void)
{
errno_t e;
return 0;
}
これは驚くべきことにこのエラーを引き起こします:
main.c:5:5: error: use of undeclared identifier 'errno_t'
errno_t x;
^
私はトレースをたどり始めました:コンパイラが<...>
インクルージョンを見ると、最初に/usr/include
を調べます。もちろん私はerrno.h
ファイルが見つかりました。実際には、ライセンスコメントの他に、次の1行が含まれています。
#include <sys/errno.h>
さて、/usr/include/sys
のerrno.h
で、次の行を見つけました。
#include <sys/cdefs.h>
#if defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1
#include <sys/_types/_errno_t.h>
#endif
そして、/usr/include/_types
の_errno_t.h
で、私はこれを見つけました:
typedef int errno_t;
つまり、そこにあり、整数型のエイリアスであり、errno.h
の一部であるように見えます。
では、なぜ含まれていないのですか?コンパイラが宣言されていない識別子エラーを発生させるのはなぜですか?
前もって感謝します!
関連情報:
Compiler:
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)`
Compiler flags:
-std=c11 -I/usr/include/sys -I/usr/local/include
マクロ変数__STDC_WANT_LIB_EXT1__
は、次の行の/usr/include/sys
のcdefs.h
で定義されます。
/* If the developer has neither requested a strict language mode nor a version
* of POSIX, turn on functionality provided by __STDC_WANT_LIB_EXT1__ as part
* of __DARWIN_C_FULL.
*/
#if !defined(__STDC_WANT_LIB_EXT1__) && !defined(__STRICT_ANSI__) && __DARWIN_C_LEVEL >= __DARWIN_C_FULL
#define __STDC_WANT_LIB_EXT1__ 1
#endif
UPDATE:
@PaulRがコメントセクションで述べたように、-std=c11
フラグを削除すると、コンパイルされます。これは、フラグが含まれている場合に発生するエラーと同じくらい驚くべきことです。したがって、この質問をサブ質問で拡張します。
C11標準のerrno_t
部分ではない、または標準がコンパイラーに指定されているのになぜ含まれないのですか?
errno_t
は標準タイプではありません。これはオプションの(そして広く嫌われ、サポートされていない)Annex Kの一部であり、標準を無視して妨害した歴史を持つ特定のベンダーのためにのみISOC11に含まれています。
AnnexKはerrno_t
をint
として定義しているため、errno
オブジェクトのタイプはint
であり、すべてのエラーコードはint
です。プログラム内のint
。サポートされる可能性が低いオプション機能に依存するよりもはるかに移植性があります。