2010-07-28 10 views
10

Questo semplice file .c:unistd.h e C99 su Linux

#include <unistd.h> 

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

... quando compilato normalmente, funziona bene:

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

... ma quando compilato in modalità C99, dà un avvertimento:

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

Il file .o risultante va bene e il collegamento funziona. Mi piacerebbe solo sbarazzarmi dell'avvertimento. Posso ottenere questo in modo hacky, inserendo le dichiarazioni nel mio file .h.

Di cosa si tratta C99, ciò significa che le dichiarazioni in unistd.h non vengono incluse? Questo può essere superato, senza rinunciare alla simpatia di C99?

Vedo lo stesso problema per altre librerie standard.

risposta

15

Potrebbe essere necessario definire alcune macro in modo particluar per ottenere il prototipo per gethostname()

Da man gethostname:

Test delle funzioni e requisiti delle macro per glibc (vedi feature_test_macros (7)):

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

Quindi:

#define _BSD_SOURCE 

#include <unistd.h> 

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

I dettagli scabrosi:

Se non si specifica l'opzione -std-c99, quindi features.h (che è implicitamente incluso per unistd.h) si imposterà a impostare _BSD_SOURCE in modo tale che il prototipo per gethostname() viene incluso . Tuttavia, specificando -std=c99 il compilatore definisce automaticamente __STRICT_ANSI__, che a sua volta causa features.h per non definire _BSD_SOURCE, a meno che non lo si imponga con la propria definizione di macro funzione (come sopra).

+0

+1 Trattamento molto accurato. –

+1

+1 per una risposta. -10 per il '#define _BSD_SOURCE'. Si prega di utilizzare '#define _XOPEN_SOURCE 500' o meglio ancora nella catena di build:' cc -D_XOPEN_SOURCE = 500 ... '. Bene, questo se si desidera qualsiasi tipo di portabilità. – Dummy00001

+0

Come con la mia risposta a Luther - 'man gethostname' sul mio sistema Red Hat non fa menzione dei Requisiti Macro di Feature Test. Qualcuno ha qualche idea del perché? – slim

10

gethostname() non è una funzione C standard (non è menzionata in nessun punto nello standard C99), pertanto il simbolo non viene definito correttamente durante la compilazione sullo standard.

Se si utilizza la toolchain gcc, utilizzare -std=gnu99 e si otterrà il comportamento desiderato.

In alternativa, guardando <features.h>, sembra che si potrebbe usare -D_GNU_SOURCE o -D_XOPEN_SOURCE=500 per ottenere il comportamento desiderato.

+0

Anche se ho accettato una risposta diversa, '-std = gnu99' è la correzione che ho effettivamente utilizzato. Grazie. – slim

+0

Ho appena trovato esattamente questo problema e ho scelto anche '-std = gnu99'. – Cubbi

4

Leggi man gethostname. Dice nei Requisiti Macro di Feature Test, che è richiesto _BSD_SOURCE (o _XOPEN_SOURCE>500) per estrarre gethostname da unistd.h.

Continua a leggere man feature_test_macros. Troverete che -std=c99 attiva __STRICT_ANSI__ che in disattiva_BSD_SOURCE.Ciò significa che non è possibile ottenere gethostname da unistd.h a meno che non si definisca nuovamente _BSD_SOURCE. Di solito posto _GNU_SOURCE sulla mia riga di comando (ad esempio gcc -D_GNU_SOURCE -std=c99 file.c) per la maggior parte delle cose, che si attiva anche su _BSD_SOURCE.

P.S. La pagina di manuale contiene un programma di esempio che può stampare i ft-macros correnti. Potresti compilarlo ed eseguirlo per alcune impostazioni del compilatore.

+0

Nessuno di questi è in 'man gethostname' sul mio sistema RedHat. Su quale sistema è tuo? Dovrei installare altre manpage? – slim