2010-07-28 4 views
10

Ce fichier .c simple:unistd.h et C99 sur Linux

#include <unistd.h> 

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

... quand compilé normalement, fonctionne très bien:

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

... mais quand compilé en mode C99, donne un avertissement:

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

Le fichier résultant est bien, et reliant des œuvres. Je voudrais juste me débarrasser de l'avertissement. Je peux y arriver de manière hacker, en mettant des déclarations dans mon propre fichier .h. Qu'est-ce que C99 signifie que les déclarations dans unistd.h ne sont pas incluses? Cela peut-il être surmonté, sans renoncer à la gentillesse de C99?

Je vois le même problème pour les autres librairies standard.

Répondre

15

Vous devrez peut-être définir des macros de manière particluar pour obtenir le prototype de gethostname()

De man gethostname:

Test Feature Exigences pour les macros glibc (voir (7)):

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

donc:

#define _BSD_SOURCE 

#include <unistd.h> 

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

Les détails sordides:

Si vous ne spécifiez pas l'option -std-c99, puis features.h (qui est implicitement inclus par unistd.h) sera par défaut à la mise en _BSD_SOURCE de telle sorte que le prototype de gethostname() sera inclus . Cependant, en spécifiant -std=c99, le compilateur définit automatiquement __STRICT_ANSI__, ce qui à son tour provoque features.h de ne pas définir _BSD_SOURCE, sauf si vous le forcez avec votre propre définition de macro de fonction (comme ci-dessus).

+0

+1 Traitement très approfondi. –

+1

+1 pour une réponse. -10 pour le '#define _BSD_SOURCE'. Veuillez s'il vous plaît utiliser '#define _XOPEN_SOURCE 500' ou mieux encore dans la chaîne de compilation:' cc -D_XOPEN_SOURCE = 500 ... '. Eh bien, que si une forme de portabilité est souhaitée. – Dummy00001

+0

Comme pour ma réponse à Luther - 'man gethostname' sur mon système Red Hat ne fait aucune mention des exigences de macro de test de fonctionnalité. Quelqu'un a une idée de pourquoi? – slim

10

gethostname() n'est pas une fonction C standard (elle n'est mentionnée nulle part dans la norme C99), donc le symbole n'est pas correctement défini lors de la compilation à la norme.

Si vous utilisez la chaîne d'outils gcc, utilisez -std=gnu99 et vous obtiendrez le comportement souhaité.

Alternativement, en regardant <features.h>, il semble que vous pourriez utiliser -D_GNU_SOURCE ou -D_XOPEN_SOURCE=500 pour obtenir le comportement désiré.

+0

Bien que j'aie accepté une réponse différente, '-std = gnu99' est le correctif que j'ai réellement utilisé. Merci. – slim

+0

Juste rencontré exactement ce problème, et a choisi de '-std = gnu99' ainsi. – Cubbi

4

Lecture man gethostname. Il est dit dans les exigences de macro de test de fonctionnalités que _BSD_SOURCE (ou _XOPEN_SOURCE>500) est requis pour extraire le nom d'hôte de unistd.h.

Ensuite, lisez man feature_test_macros. Vous constaterez que -std=c99 allume __STRICT_ANSI__ qui dans désactive_BSD_SOURCE.Cela signifie que vous ne pouvez pas obtenir gethostname à partir de unistd.h, sauf si vous définissez à nouveau _BSD_SOURCE. Je place généralement _GNU_SOURCE sur ma ligne de commande (c'est-à-dire gcc -D_GNU_SOURCE -std=c99 file.c) pour la plupart des choses, ce qui active également _BSD_SOURCE.

P.S. La page de manuel contient un exemple de programme qui peut imprimer les ft-macros actuelles. Vous pouvez le compiler et l'exécuter pour certains paramètres du compilateur.

+0

Rien de tout cela n'est dans 'man gethostname' sur mon système redhat. Quel système est le vôtre? Dois-je installer des pages de manuel supplémentaires? – slim

Questions connexes