0

Why does this C code compile in C99? What should I read to learn more?

I can't post unless I add more text so here's some nonsense text because I don't think there's anything else to say

$ cat m.c
#include <stdio.h>
#include <time.h>
int main() {
    struct timespec time;
    int res = clock_gettime(CLOCK_REALTIME, &time);
    printf("%d %ld %ld\n", res, time.tv_sec, time.tv_nsec);
    return 0;
}


$ clang m.c && ./a.out && rm ./a.out
0 1631386905 774654955


$ clang -std=c99 m.c && ./a.out && rm ./a.out
m.c:4:18: error: variable has incomplete type 'struct timespec'
        struct timespec time;
                        ^
m.c:4:9: note: forward declaration of 'struct timespec'
        struct timespec time;
            ^
m.c:5:12: warning: implicit declaration of function 'clock_gettime' is invalid in C99 [-Wimplicit-function-declaration]
        int res = clock_gettime(CLOCK_REALTIME, &time);
                ^
m.c:5:26: error: use of undeclared identifier 'CLOCK_REALTIME'
        int res = clock_gettime(CLOCK_REALTIME, &time);
                                ^
1 warning and 2 errors generated.
user3840170
  • 26,597
  • 4
  • 30
  • 62
Eric Stotch
  • 141
  • 4
  • 19
  • does this answer? https://stackoverflow.com/questions/3875197/gcc-with-std-c99-complains-about-not-knowing-struct-timespec c11 has it, and some other stuff (posix) has it. just c99 does not. enable that other stuff if using c99 – Abel Sep 14 '21 at 00:31
  • 2
    `clock_gettime` is not a part of C99, the code could be compiled either with the GNU99 extension `-std=gnu99`, or with the `#define _POSIX_C_SOURCE 200112L` macro – skink Sep 14 '21 at 00:35
  • The "invalid in C99" is because without the POSIX feature test macros enabled, `` doesn't contain a declaration of `clock_gettime`. Prior to C99 it was legal (though usually wrong) to use a function even if hadn't been declared; the compiler assumed an *implicit declaration* of the function as returning `int` and taking unspecified arguments. In C99 this was made undefined behavior, but GCC will still provide the older behavior after giving a warning. Anyway, you don't want any of that; the right fix is to define the feature test macro and get the proper declaration from ``. – Nate Eldredge Sep 14 '21 at 00:43

1 Answers1

4

It’s because using the -std=c99 option defines a macro that causes the declaration of clock_gettime to be hidden.

The GNU C library can expose different versions of its functions, or hide them altogether, depending on what is expected by user code. User code declares those expectations by defining certain specially-named macros (called feature test macros, though this is something of a misnomer) with pre-determined values recognised by the GNU C library headers. One such macro is __STRICT_ANSI__, which is implicitly defined if any of the -std=cXX options are used.

Quoting feature_test_macros(7):

__STRICT_ANSI__

ISO Standard C. This macro is implicitly defined by gcc(1) when invoked with, for example, the -std=c99 or -ansi flag.

[…]

If any of __STRICT_ANSI__, _ISOC99_SOURCE, _ISOC11_SOURCE (since glibc 2.18), _POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE, _XOPEN_SOURCE_EXTENDED (in glibc 2.11 and earlier), _BSD_SOURCE (in glibc 2.19 and earlier), or _SVID_SOURCE (in glibc 2.19 and earlier) is explicitly defined, then _BSD_SOURCE, _SVID_SOURCE, and _DEFAULT_SOURCE are not defined by default.

Using -std=gnuXX option instead of -std=cXX does not cause __STRICT_ANSI__ to be defined; it also enables GNU extensions to the C language. If you want to keep those language extensions disabled, you can instead put #define _DEFAULT_SOURCE 1 at the very top of the file to expose all the symbols the C library otherwise would expose (or perhaps another feature test macro to adjust the library interface to your liking). An explicit feature test macro will take precedence over __STRICT_ANSI__.

user3840170
  • 26,597
  • 4
  • 30
  • 62