简体   繁体   中英

unistd.h and c99 on Linux

This simple .c file:

#include <unistd.h>

void test() {
   char string[40];
   gethostname(string,40);
}

... when compiled normally, works fine:

$ cc  -Wall -c -o tmp.o tmp.c
$

... but when compiled in C99 mode, gives a warning:

$ cc -Wall -std=c99 -c -o tmp.o tmp.c 
tmp.c: In function `test':
tmp.c:5: warning: implicit declaration of function `gethostname'
$

The resultant .o file is fine, and linking works. I'd just like to get rid of the warning. I can achieve this in a hacky way, by putting declarations in my own .h file.

What is it about C99 that means the declarations in unistd.h don't get included? Can this be overcome, without giving up the niceness of C99?

I see the same problem for other standard libs.

You may need to define some macros in a particluar way to get the prototype for gethostname()

From man gethostname :

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

  gethostname(): _BSD_SOURCE || _XOPEN_SOURCE >= 500 sethostname(): _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500) 

So:

#define _BSD_SOURCE

#include <unistd.h>

void test() {
   char string[40];
   gethostname(string,40);
}

The gory details:

If you don't specify the -std-c99 option, then features.h (which is implicitly included by unistd.h ) will default to setting _BSD_SOURCE in such a way that the prototype for gethostname() gets included. However, specifying -std=c99 causes the compiler to automatically define __STRICT_ANSI__ , which in turn causes features.h to not define _BSD_SOURCE , unless you force it with your own feature macro definition (as above).

gethostname( ) is not a standard C function (it's not mentioned anywhere in the C99 standard), so the symbol is correctly not defined when compiling to the standard.

If you're using the gcc toolchain, use -std=gnu99 and you'll get the behavior you want.

Alternatively, looking at <features.h> , it seems like you could use -D_GNU_SOURCE or -D_XOPEN_SOURCE=500 to get the desired behavior.

Read man gethostname . It says in the Feature Test Macro Requirements, that _BSD_SOURCE (or _XOPEN_SOURCE>500 ) is required to pull gethostname from unistd.h.

Next read man feature_test_macros . You will find that -std=c99 turns on __STRICT_ANSI__ which in turns off _BSD_SOURCE . This means you can't get gethostname from unistd.h unless you define _BSD_SOURCE again. I usually place _GNU_SOURCE on my command line (ie gcc -D_GNU_SOURCE -std=c99 file.c ) for most things, which turns on _BSD_SOURCE as well.

PS The manual page contains an example program which can print the current ft-macros. You might compile and run it for some compiler settings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM