Avertissement du compilateur "Pas de nouvelle ligne à la fin du fichier"

191

Quelle est la raison de l'avertissement suivant dans certains compilateurs C ++?

Pas de nouvelle ligne à la fin du fichier

Pourquoi devrais-je avoir une ligne vide à la fin d'un fichier source / en-tête?

Brian Tompsett - 汤 莱恩
la source
17
Pas vraiment la raison, mais c'est très ennuyeux si vous avez catun fichier et qu'il n'a pas de nouvelle ligne à la fin car la nouvelle invite du shell apparaîtra après la dernière ligne du fichier (c'est-à-dire pas dans la colonne 0)
ThiefMaster
@ThiefMaster My $ PS1 commence par une nouvelle ligne pour cette raison même. (c'est de toute façon une invite sur plusieurs lignes, contenant un tas d'informations utiles sur une ligne, puis rien d'autre qu'un caractère d'invite sur la suivante pour que les commandes assez longues ne s'enroulent pas)
bames53
7
Why should I have an empty line at the end of a source/header file- Si un fichier texte contient one\ntwo\nthree\nalors il contient trois lignes, dont aucune n'est vide. Si un fichier texte contient one\ntwo\nthreealors ce n'est pas un fichier texte, dans le même sens qu'une phrase sans point à la fin n'est pas une phrase.
Brandin le

Réponses:

220

Pensez à certains des problèmes qui peuvent survenir s'il n'y a pas de nouvelle ligne. Selon la norme ANSI, #includeun fichier au début insère le fichier exactement tel quel au début du fichier et n'insère pas la nouvelle ligne après le #include <foo.h>après le contenu du fichier. Donc, si vous incluez un fichier sans nouvelle ligne à la fin de l'analyseur, il sera affiché comme si la dernière ligne de foo.hest sur la même ligne que la première ligne de foo.cpp. Et si la dernière ligne de foo.h était un commentaire sans nouvelle ligne? Maintenant, la première ligne de foo.cppest commentée. Ce ne sont là que quelques exemples des types de problèmes qui peuvent surgir.


Je voulais juste indiquer aux parties intéressées la réponse de James ci-dessous. Bien que la réponse ci-dessus soit toujours correcte pour C, la nouvelle norme C ++ (C ++ 11) a été modifiée afin que cet avertissement ne soit plus émis si vous utilisez C ++ et un compilateur conforme à C ++ 11.

De la norme C ++ 11 via le post de James:

Un fichier source qui n'est pas vide et qui ne se termine pas par un caractère de nouvelle ligne, ou qui se termine par un caractère de nouvelle ligne immédiatement précédé d'une barre oblique inverse avant qu'un tel épissage n'ait lieu, doit être traité comme si un nouveau - les caractères de ligne ont été ajoutés au fichier (C ++ 11 §2.2 / 1).

TJ Seabrooks
la source
29
Bien sûr, dans la pratique, chaque compilateur ajoute une nouvelle ligne après le #include. Heureusement.
mxcl
3
Je me souviens qu'une ancienne version de Microsoft Visual C ++ (comme 2.x ou quelque chose) avait exactement ce problème. Cela a été exacerbé parce que l'éditeur IDE a encouragé ce genre de comportement de nouvelle ligne manquante.
Greg Hewgill
2
Les compilateurs peuvent ne pas se plaindre actuellement, mais GitHub le fait réellement.
Puyover
1
Je peux voir la réponse "ci-dessous" de James mais: "La réponse ci-dessus" dans OrderBy what?! Ci-dessus se trouve la question, comme je l'ordonne habituellement par votes. Ou voulez-vous dire votre propre réponse?
mbx
@Thomas: Ce programme appelle-t-il un comportement non défini car il ne se termine pas par une nouvelle ligne. Voir le programme ici: ideone.com/jswwf9
Destructor
46

L'exigence que chaque fichier source se termine par une nouvelle ligne non échappée a été supprimée dans C ++ 11. La spécification se lit maintenant:

Un fichier source qui n'est pas vide et qui ne se termine pas par un caractère de nouvelle ligne, ou qui se termine par un caractère de nouvelle ligne immédiatement précédé d'une barre oblique inverse avant qu'un tel épissage n'ait lieu, doit être traité comme si un nouveau - les caractères de ligne ont été ajoutés au fichier (C ++ 11 §2.2 / 1).

Un compilateur conforme ne devrait plus émettre cet avertissement (du moins pas lors de la compilation en mode C ++ 11, si le compilateur a des modes pour différentes révisions de la spécification du langage).

James McNellis
la source
4
C'est bien beau pour C ++; malheureusement, C dit toujours que c'est UB, même dans le dernier projet de la prochaine norme C1X.
Adam Rosenfield
11
Cette question est étiquetée [c ++] et non [c].
James McNellis
3
Même ainsi, il devrait probablement être marqué [c], car de nombreuses personnes recherchant cet avertissement en C trouveront leur chemin ici.
Adam Rosenfield
1
C'est encore un bon point à ajouter. En ajoutant cela ci-dessus. J'espère que cela ne vous dérange pas.
TJ Seabrooks
27

La norme C ++ 03 [2.1.1.2] déclare:

... Si un fichier source qui n'est pas vide ne se termine pas par un caractère de nouvelle ligne ou se termine par un caractère de nouvelle ligne immédiatement précédé d'une barre oblique inverse avant qu'un tel épissage ait lieu, le comportement n'est pas défini.

Igor Semenov
la source
16

La réponse pour «obéissant» est «parce que la norme C ++ 03 dit que le comportement d'un programme ne se terminant pas par une nouvelle ligne n'est pas défini» (paraphrasé).

La réponse pour les curieux est ici: http://gcc.gnu.org/ml/gcc/2001-07/msg01120.html .

Vytautas Shaltenis
la source
5
Ahh, le "comportement indéfini" bien-aimé. Quand d'autres langages échouent, c / c ++ se comporte de manière "indéfinie" :) C'est certainement une grande partie de leur charme. Et je ne plaisante pas.
shylent
6

Cela ne fait pas référence à une ligne vide, mais à savoir si la dernière ligne (qui peut contenir du contenu) se termine par une nouvelle ligne.

La plupart des éditeurs de texte mettront une nouvelle ligne à la fin de la dernière ligne d'un fichier, donc si la dernière ligne n'en a pas, il y a un risque que le fichier ait été tronqué. Cependant, il existe des raisons valables pour lesquelles vous ne voudrez peut-être pas la nouvelle ligne, ce n'est donc qu'un avertissement, pas une erreur.

Leigh Caldwell
la source
5

#includeremplacera sa ligne par le contenu littéral du fichier. Si le fichier ne se termine pas par une nouvelle ligne, la ligne contenant le #includequi l'a tiré fusionnera avec la ligne suivante.

l'ombre de la lune
la source
2

J'utilise la version 5.0 de l'IDE sans c, dans mon programme, soit le langage `` c ++ '' ou `` c '', je recevais le même problème.Juste à la fin du programme, c'est-à-dire la dernière ligne du programme (après les accolades de la fonction, cela peut être principale ou n'importe quelle fonction), appuyez sur Entrée -line no. sera augmenté de 1. puis exécutez le même programme, il fonctionnera sans erreur.

plongée
la source
2

Bien sûr, dans la pratique, chaque compilateur ajoute une nouvelle ligne après le #include. Heureusement. - @mxcl

pas de C / C ++ spécifique mais un dialecte C: lors de l'utilisation de l' GL_ARB_shading_language_includeextension, le compilateur glsl sous OS X vous avertit PAS d'une nouvelle ligne manquante. Ainsi , vous pouvez écrire un MyHeader.hfichier avec un garde d' en- tête qui se termine par #endif // __MY_HEADER_H__et vous allez perdre la ligne après la #include "MyHeader.h"certitude.

Jan-Philip Loos
la source
2

Parce que le comportement diffère entre les versions C / C ++ si le fichier ne se termine pas par une nouvelle ligne. Les anciennes versions de C ++ sont particulièrement désagréables, fx en C ++ 03, le standard dit (phases de traduction):

Si un fichier source qui n'est pas vide ne se termine pas par un caractère de nouvelle ligne ou se termine par un caractère de nouvelle ligne immédiatement précédé par une barre oblique inverse, le comportement n'est pas défini.

Un comportement non défini est mauvais: un compilateur conforme standard pourrait faire plus ou moins ce qu'il veut ici (insérer du code malveillant ou autre) - clairement une raison d'avertissement.

Bien que la situation soit meilleure dans C ++ 11, il est judicieux d'éviter les situations où le comportement n'est pas défini dans les versions antérieures. La spécification C ++ 03 est pire que C99 qui interdit catégoriquement de tels fichiers (le comportement est alors défini).

skier
la source
Je soupçonne que la norme a déclaré que les programmes sans la nouvelle ligne de fin ont un comportement indéfini, plutôt que de déclarer qu'ils étaient mal formés, car certains compilateurs concaténeraient une ligne finale non terminée d'un fichier inclus avec le texte du code source suivant la #includedirective , et certains programmeurs ciblant de tels compilateurs peuvent avoir exploité un tel comportement. Le fait que la norme laisse de telles choses non définies permettrait aux programmes exploitant ces bizarreries d'être bien définis sur les plates-formes qui spécifient un tel comportement. Avoir le mandat de la norme un comportement briserait ces programmes.
supercat
0

Cet avertissement peut également aider à indiquer qu'un fichier a pu être tronqué d'une manière ou d'une autre. Il est vrai que le compilateur lancera probablement une erreur de compilateur de toute façon - surtout si c'est au milieu d'une fonction - ou peut-être une erreur de l'éditeur de liens, mais cela pourrait être plus cryptique et ne pas être garanti.

Bien sûr, cet avertissement n'est pas non plus garanti si le fichier est tronqué immédiatement après une nouvelle ligne, mais il peut toujours détecter certains cas que d'autres erreurs pourraient manquer et donner une indication plus forte du problème.

mwfearnley
la source
-2

Ce n'est pas une erreur. C'est juste un avertissement.

Ouvrez le fichier dans un éditeur, accédez à la dernière ligne du fichier et appuyez sur Entrée pour ajouter une ligne vide à la fin du fichier.

Cependant, en plus de cela, vous devriez utiliser à la #include <iostream>place de <iostream.h>. Ensuite, mettez un using std::cout;après.

keya
la source