Question

Transcription de la session:

>type lookma.c
int main() {
  printf("%s", "no stdio.h");
}

>cl lookma.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

lookma.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:lookma.exe
lookma.obj

>lookma
no stdio.h
Était-ce utile?

La solution

En mode de conformité strict (cela signifie "en théorie"), vous appelez un comportement indéfini (ce qui est mauvais) lorsque vous appelez une fonction qui prend un nombre variable d'arguments sans déclaration prototype de la fonction dans la portée. Cela signifie que le compilateur est autorisé à faire tout ce qu'il veut avec un programme utilisant printf () sans le prototype de #include < stdio.h > ou une déclaration équivalente . "Tout ce qui lui plaît" includes fonctionne correctement comme l'une des options; cela semble être l'option choisie par votre exemple.

En pratique, le code fonctionnera correctement avec la plupart des compilateurs pratiques, même sans la déclaration formelle de la fonction printf () .

Comme qrdl l’a souligné, la fonction a été trouvée car le compilateur C est lié à la bibliothèque C.

Notez que le commentaire de Chris Young sur C99 et sur "implicit int" est exact, mais que la règle concernant les "fonctions d'arguments variables doit avoir un prototype dans la portée" s'applique à la fois à C89 et à C99. La plupart des compilateurs ne fonctionnent pas dans un mode de compatibilité C99 strict par défaut car il y a trop de code qui ne pourrait pas être compilé comme ça.

Chris Young a commenté:

  

Pour clarifier, mon commentaire concernait la suppression des déclarations implicites par C99. En disant "implicit int", je pense que vous faites référence à la fonctionnalité C89 consistant à autoriser des déclarations telles que foo (void); signifie int foo (vide); quelque chose de C99 a également été supprimé.

Chris a bien sûr raison. Deux fonctionnalités de «déclaration implicite» ont été supprimées de la norme C99. L’avant-propos de la norme les répertorie comme suit:

  • supprime int implicite
  • supprime la déclaration de fonction implicite

Je ne pensais pas (et donc n'écrivais pas) assez clairement. Néanmoins, C89 et C99 requièrent tous deux un prototype pour les fonctions utilisant un nombre variable d'arguments.

Pour illustrer:

extern int pqr();
int main(void)
{
    int i = pqr(1, 3);
    return i;
}

Sans la première ligne, il s'agit d'un fragment C89 correct avec une déclaration implicite de la fonction pqr () en tant que fonction renvoyant un entier (avec des arguments non spécifiés). Si la première ligne est remplacée par extern pqr (); , il s'agit d'un fragment C89 correct avec une déclaration explicite de pqr () en tant que fonction renvoyant un entier ( avec des arguments non spécifiés), mais le type de retour est 'implicit int '. Comme écrit, la fonction est explicitement déclarée et a un type de retour int explicite - mais elle a toujours des arguments non spécifiés. Je crois que cela est valable C99 - bien que ce ne soit pas totalement souhaitable. Certes, GCC (3.4.4) l’accepte avec les options -std = c99 -pedantic "." Idéalement, la déclaration de fonction devrait inclure le prototype complet. (Et si pqr () était défini avec des points de suspension, ce prototype serait requis en théorie !)

Autres conseils

Vous aviez initialement étiqueté ce C ++, mais il semblerait que ce soit un programme C. C fournira automatiquement une déclaration implicite pour une fonction s'il n'y a pas de prototype dans la portée (par exemple, en raison de l'omission de #include < stdio.h >). La déclaration implicite serait:

int printf();

Cela signifie que printf est une fonction qui retourne un entier et peut prendre un nombre illimité d'arguments. Ce prototype est arrivé à travailler pour votre appel. Vous devez #inclure

Enfin, je devrais ajouter que la norme C actuelle (ISO / CEI 9899: 1999 ou "C99" de manière familière) n'autorise pas les déclarations implicites et que ce programme ne serait pas conforme. Les déclarations implicites ont été supprimées. Je crois que votre compilateur ne supporte pas C99. C ++ requiert également des prototypes corrects et ne fait pas de déclarations implicites.

printf () se trouve dans la bibliothèque standard C et l’éditeur de liens lie toujours la bibliothèque standard à votre exécutable. Ainsi, toutes les fonctions standard seront trouvées et aucun problème de liaison ne se produira.

Si vous n'incluez pas les en-têtes appropriés, vous utiliserez une fonction non prototypée, ce qui peut poser problème, car le compilateur C suppose que cette fonction sans prototype renvoie int et prend un nombre variable d'arguments. Donc, toujours inclure l'en-tête - c'est votre barrière de sécurité.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top