web-dev-qa-db-ja.com

-std = c99を指定したGCCは、struct timespecを知らないというメッセージを表示します

Linuxでgcc -std=c99を使用してこれをコンパイルしようとすると、コンパイラはstruct timespecを知らないというメッセージを表示します。ただし、これを-std=c99なしでコンパイルすると、すべて正常に動作します。

#include <time.h>

int main(void)
{
  struct timespec asdf;
  return 0;
}

これはなぜですか、それでも-std=c99で動作させる方法はありますか?

41
Nils

POSIX機能を明示的に有効にする

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)からの定義をトリガーします。

  • POSIX 2008 (SUS v4)資料が必要な場合は、__XOPEN_SOURCE 700_を使用してください
  • POSIX 2004 (SUS v3)資料が必要な場合は、__XOPEN_SOURCE 600_を使用してください
  • POSIX 1995 (SUS v2、1997)資料が必要な場合は、__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の使用に失敗しました。

GCCは_-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はありませんでした。

ヘッダーを使用してPOSIXバージョン情報を制御する

現在(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 サブディレクトリ内。

C11は_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_は自動的に定義されます。

57

-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
40
Bill Lynch

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.  */
 }; 
1
Mike Seeds