Question

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_t1:

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, and time_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?

Was it helpful?

Solution

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.

OTHER TIPS

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:

  1. 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.

  2. 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.

  3. 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).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top