Linuxでgcc -std=c99
を使用してこれをコンパイルしようとすると、コンパイラはstruct timespec
を知らないというメッセージを表示します。ただし、これを-std=c99
なしでコンパイルすると、すべて正常に動作します。
#include <time.h>
int main(void)
{
struct timespec asdf;
return 0;
}
これはなぜですか、それでも-std=c99
で動作させる方法はありますか?
TimespecはPOSIXから取得されるため、POSIX定義を「有効」にする必要があります。
_#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif /* __STDC_VERSION__ */
#include <time.h>
void blah(struct timespec asdf)
{
}
int main()
{
struct timespec asdf;
return 0;
}
_
一番上のスタンザは私が現在使用しているものです。これは、C99またはC89コンパイラーを使用しているかどうかに基づいて、Single UNIX Specification(SUS)からの定義をトリガーします。
_XOPEN_SOURCE 700
_を使用してください_XOPEN_SOURCE 600
_を使用してください_XOPEN_SOURCE 500
_を使用しますコメントに記載されているように、__XOPEN_SOURCE
_を使用すると、厳密なPOSIXよりもXSI(X/Open System Interface)拡張が厳密に有効になりますが、XSIではなくPOSIXが必要になることはほとんどありません。通常は__XOPEN_SOURCE
_を指定し、__POSIX_C_SOURCE
_を使用してファッツを指定しないでください。機能マクロの詳細については、 コンパイル環境 の(POSIX 2018)を参照してください。
2010年の私のシステムでは、POSIX 2008はPOSIX 2004ほど広く利用できなかったので、それを使用しましたが、YMMVでした。 SUS v3とv4はどちらもC99コンパイルが必要です。Solarisでは、少なくともC89の使用に失敗しました。
-std=gnuXX
_オプションを提供します_-std=c11
_をGCC(またはGCCをエミュレートするClang)に指定すると、標準のC定義のみが有効になります。 _-std=gnu11
_を使用すると、POSIXおよびその他の標準Cの拡張機能がデフォルトで表示されます。
GCC 4.x以前では、デフォルトで_-std=gnu90
_(C90 plus拡張に対応)を使用していたことに注意してください。 GCC 5.x以降では、デフォルトで_-std=gnu11
_を使用します。デフォルトで_-std=gnu99
_を有効にするバージョンのGCCはありませんでした。
現在(2019)はヘッダーを使用してこの情報をカプセル化しているため、将来の変更ではPOSIX機能を使用するすべてのソースファイルではなく、単一のヘッダーを変更するだけで済みます。時間の経過とともに複数のソースファイルから古いスタンザを編集するのは面倒で、POSIX 2008が普及しました。
_/*
@(#)File: $RCSfile: posixver.h,v $
@(#)Version: $Revision: 1.4 $
@(#)Last changed: $Date: 2017/06/18 00:15:42 $
@(#)Purpose: Request appropriate POSIX and X/Open Support
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 2010-2017
*/
/*TABSTOP=4*/
#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H
/*
** Include this file before including system headers. By default, with
** C99 support from the compiler, it requests POSIX 2008 support. With
** C89 support only, it requests POSIX 1997 support. Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/
/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */
#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if defined(__cplusplus)
#define _XOPEN_SOURCE 700 /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */
#Elif __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 700 /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */
#else
#define _XOPEN_SOURCE 500 /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */
#endif /* JLSS_ID_POSIXVER_H */
_
Stack Overflowで使用される「CC by-sa 3.0」ライセンスで通常必要とされる帰属および著作権表示なしで、このヘッダーの情報を使用できます。このコードは、GitHubのmy [〜#〜] soq [〜#〜] (Stack Overflow Questions)リポジトリでファイル_posixver.h
_として利用できます src/libsoq サブディレクトリ内。
struct timespec
_を定義しますC11 は_struct timespec
_を定義し、POSIX(最初に定義した)と互換性のある方法で定義することに注意してください。
ヘッダー _<time.h>
_ はタイプを定義します。これを使用する関数のうち3つは _<threads.h>
_ で宣言され、もう1つは_<time.h>
_で宣言されています。
これらはもちろんC17(C18)の一部でもあります。 _-std=c11
_または同様のものでコンパイルする必要があります(GCC 9.2.0は_-std=c17
_と_-std=c18
_の両方を認識しているようです。また、標準の次のバージョンでは_-std=c2x
_)タイプ_struct timespec
_は自動的に定義されます。
-std=gnu99
でコンパイルすることをお勧めします。
これについて詳しく説明します。デフォルトでは、gccは-std = gnu89でコンパイルされます。以下は、次のソースコードの結果です。
#include <time.h>
int main() {
struct timespec asdf;
return 0;
}
[1:25pm][wlynch@cardiff /tmp] gcc -std=gnu89 foo.c
[1:26pm][wlynch@cardiff /tmp] gcc -std=gnu99 foo.c
[1:25pm][wlynch@cardiff /tmp] gcc -std=c89 foo.c
foo.c: In function ‘main’:
foo.c:4: error: storage size of ‘asdf’ isn’t known
[1:26pm][wlynch@cardiff /tmp] gcc -std=c99 foo.c
foo.c: In function ‘main’:
foo.c:4: error: storage size of ‘asdf’ isn’t known
CFLAGSに-D_GNU_SOURCEを追加しても機能します。
gcc test.c -o test -std = c99 -D_GNU_SOURCE
/usr/include/time.hを見てください。これは、timespec定義をラップする条件付きプリプロセッサーです。 _GNU_SOURCEは__USE_POSIX199309を有効にします。
#if (!defined __timespec_defined \
&& ((defined _TIME_H \
&& (defined __USE_POSIX199309 \
|| defined __USE_ISOC11)) \
|| defined __need_timespec))
# define __timespec_defined 1
struct timespec
{
__time_t tv_sec; /* Seconds. */
__syscall_slong_t tv_nsec; /* Nanoseconds. */
};