Reputation: 92976
I'm experiencing a strange problem with some C code I am writing. Consider the following code:
#include <sys/stat.h>
ino_t inode;
According to POSIX.1-2008, the header file <sys/stat.h> defines ino_t
1:
The <sys/stat.h> header shall define the
blkcnt_t
,blksize_t
,dev_t
,ino_t
,mode_t
,nlink_t
,uid_t
,gid_t
,off_t
, andtime_t
types as described in <sys/types.h>.
This happens when I try to compile the source code above places in a file test.c on my Linux system:
$ cat test.c #include <sys/stat.h> ino_t inode; $ uname -srm Linux 3.8.0-26-generic x86_64 $ lsb_release -d Description: Ubuntu 13.04 $ gcc -c test.c $ gcc -std=c90 test.c test.c:2:1: error: unknown type name 'ino_t' $ gcc -std=c99 test.c test.c:2:1: error: unknown type name 'ino_t' $ gcc -std=c1x test.c test.c:2:1: error: unknown type name 'ino_t'
Why is the definition of ino_t
not revelead when I specify any -std option?
Upvotes: 4
Views: 2563
Reputation: 140540
Your program would have compiled without complaint if you had used -std=gnuXX
instead of -std=cXX
.
$ cc -std=c11 -fsyntax-only test.c ; echo $?
test.c:2:1: error: unknown type name ‘ino_t’; did you mean ‘__ino_t’?
1
but
$ cc -std=gnu11 -fsyntax-only test.c ; echo $?
0
Many people don't properly understand the effects of the -std=cXX
options. They do not, by themselves, tell GCC to be strictly conforming (e.g. diagnose all use of GNU extensions). If you want strict conformance you must also give the options -Wall -Wpedantic
.
There are only three differences between a -std=cXX
mode and the corresponding -std=gnuXX
mode, and two of them are usually not what you want:
System-specific predefined macros in the application namespace are disabled in -std=cXX
mode. This one is a Good Thing; application-namespace predefined macros are confusing at best, and at worst, break legitimate code. However, it has been known to break system header files that are still looking for those macros.
Trigraphs are enabled in -std=cXX
modes and disabled in -std=gnuXX
modes. You don't want trigraphs; they were already obsolete when they were invented, and IMNSHO they should have been removed from the C standard a very long time ago.
In -std=cXX
mode, GNU libc will attempt to minimize the number of extensions above and beyond the specified C standard that are visible in its headers. (Caution: many other C libraries that GCC can be used with will not do this.) In the case of headers like sys/stat.h
that aren't part of the C standard, this is taken to mean "expose only the features that were present in the oldest version of this header we support," which is often something very old and limited, like POSIX.1-1993. This is what tripped you up. You can work around it by defining feature test macros to direct GNU libc to expose newer POSIX, etc. features.
If you are writing a new C program from scratch, I recommend you use -Wall
and -Wpedantic
(and probably a bunch of other -W
switches) but I do not recommend the use of -std=cXX
, as the only positive effect is to turn off the system-specific predefines, and that can break system headers. It is also almost always less hassle to go straight for _GNU_SOURCE
or equivalent than to futz around with trying to find a _POSIX_C_SOURCE
or _XOPEN_SOURCE
setting that gives you everything you need (particularly if you, or third-party code you bundle, might use deprecated-but-still-commonplace functions like gettimeofday
).
Upvotes: 1
Reputation: 5307
My manual page of fstat
says to also include sys/types.h
, and that solves the problem for me. The definition of ino_t
in sys/stat.h
is protected with the feature macros __USE_XOPEN
and __USE_XOPEN2K
. The definition in sys/types.h
is not protected that way.
The manual page also says to include unistd.h
, but that wasn't necessary to solve your problem.
According to the manual page of feature_test_macros
:
__STRICT_ANSI__
ISO Standard C. This macro is implicitly defined by gcc(1) when invoked with, for example, the-std=c99
or-ansi
flag.
I guess this means that any XOPEN features are also switched off. I could however not find any description of that.
P.S. It seems R.. (see below) feels that this is described also in the manual page of feature_test_macros
, but my limited brain is not able to find the exact wording, so I'd like to leave that as an exercise to the reader. If it were described anywhere, then I would expect it in that manual page indeed.
Beware that the gist of this answer is as follows:
Thou shall include all include files mentioned in a manual page and not try to reverse engineer which ones may not be needed.
Upvotes: 4