I'm reading the man page for getaddrinfo and trying to follow the example code, but it doesn't compile:
// test.c
#include <netdb.h>
void f() {
struct addrinfo t;
}
Both with clang:
$ clang -std=c11 test.c
test.c:10:21: error: variable has incomplete type 'struct addrinfo'
struct addrinfo t;
^
test.c:10:12: note: forward declaration of 'struct addrinfo'
struct addrinfo t;
^
1 error generated.
and gcc:
$ gcc -std=c11 test.c
test.c: In function ‘f’:
test.c:10:21: error: storage size of ‘t’ isn’t known
struct addrinfo t;
^
After some digging I found that the glibc headers have a preprocessor directive that "protects" (is this the right term?) the struct
from being defined, so I'm wondering:
#ifdef __USE_XOPEN2K
and others don't? what is used for? why did it change from __USE_POSIX?__USE_XOPEN2K
with -std=gnu89
, -std=gnu90
, -std=gnu99
but not with -ansi
, -std=c89
, -std=c90
, -std=c99
and -std=c11
?-std=gnuXX
or use #define __USE_XOPEN2K
?Short answer, if you are using glibc with APIs that are not part of the standard C (anything UNIX related) just use the -std=gnuXX
— this will enable a couple of features in the glibc. docs
Long answer:
This is a complex matter, the C programming language and the Unix OSs are old and have a lot of baggage; this is my try at understanding all of this.
There is a C programming language. The language appeared in the year 1972 but it was not standardized until 1989, when the first ANSI C was ratified. Currently there are these specifications of the C programming language:
The C standard has a really limited scope, it provides the syntax, semantics, and some library headers and functions. The specifications (c99 and c11) contained some predefined macros that the compiler should expose, these macros are used to indicate conformance to the standard, so that the program can use new features that older specifications didn't have, but there is no macro that the source code could use to remove features.
Besides the C programming language specification there are a couple of UNIX specifications. Trying to make a long story and convoluted history short, ignoring problems with the trademark and legalese:
At the beginning UNIX did not have a specification and it's source was sort of illegally copied and modified, the result is a long list of UNIX variants, some of which invented incompatible or conflicting APIs, like BSD's tty socket and SVR3 termio. After some time working groups were formed to standardize the OS:
The work of these groups can be describe with this incomplete timeline:
The acronyms are:
Okay, so now GCC and the glibc need to compile and link against any C program developed with any of these standards in mind, the glibc docs says:
If you compile your programs using ‘
gcc -ansi
’, you get only the ISO C library features, unless you explicitly request additional features by defining one or more of the feature macros [...]. You should define these macros by using ‘#define
’ preprocessor directives at the top of your source code files. These directives must come before any #include of a system header file [...]. This system exists to allow the library to conform to multiple standards.
GCC's docs about language's dialects states the following:
-ansi
is equivalent to-std=c90
[...]. This turns off certain features of GCC that are incompatible with ISO C90 (when compiling C code), such as the asm and typeof keywords, and predefined macros such as unix and vax that identify the type of system you are using.-std=‘c89’
is the same as-ansi
for C code.
Also the docs about standard libraries:
If you need a standard-compliant library, then you need to find one, as GCC does not provide one. The GNU C library (called glibc) provides ISO C, POSIX, BSD, SystemV and X/Open compatibility for GNU/Linux and HURD-based GNU systems;
Useful links:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With