Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unistd.h and c99 on Linux

Tags:

c

linux

unix

c99

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.

like image 307
slim Avatar asked Jul 28 '10 16:07

slim


People also ask

What is Unistd in Linux?

In the C and C++ programming languages, unistd. h is the name of the header file that provides access to the POSIX operating system API. It is defined by the POSIX. 1 standard, the base of the Single Unix Specification, and should therefore be available in any POSIX-compliant operating system and compiler.

Is Unistd H standard library?

No, unistd. h and fcntl. h , etc are not part of standard C.

What is the Unistd symbolic constant for the standard output?

The following symbolic constants for file streams are defined: STDIN_FILENO. File number of standard input (stdin). STDOUT_FILENO.

What is Fcntl h in C?

You can help to develop the work, or you can ask for assistance in the project room. fcntl. h is the header in the C POSIX library for the C programming language that contains constructs that refer to file control, e.g. opening a file, retrieving and changing the permissions of file, locking a file for edit, etc.


3 Answers

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

like image 80
Michael Burr Avatar answered Oct 19 '22 19:10

Michael Burr


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.

like image 41
Stephen Canon Avatar answered Oct 19 '22 20:10

Stephen Canon


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 (i.e. gcc -D_GNU_SOURCE -std=c99 file.c) for most things, which turns on _BSD_SOURCE as well.

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

like image 4
Nordic Mainframe Avatar answered Oct 19 '22 19:10

Nordic Mainframe