Avviso compilatore "No newline alla fine del file"


187

Qual è il motivo del seguente avviso in alcuni compilatori C ++?

Nessuna nuova riga alla fine del file

Perché dovrei avere una riga vuota alla fine di un file sorgente / intestazione?


17
Non proprio il motivo, ma è molto fastidioso se si catdispone di un file e non ha una nuova riga finale poiché il nuovo prompt della shell apparirà dopo l'ultima riga del file (cioè non nella colonna 0)
ThiefMaster

@ThiefMaster Il mio $ PS1 inizia con una nuova riga proprio per questo motivo. (è comunque un prompt a più righe, che contiene un mucchio di informazioni utili su una riga e quindi nient'altro che un carattere di prompt sulla successiva in modo che i comandi abbastanza lunghi non
vengano

7
Why should I have an empty line at the end of a source/header file- Se un file di testo contiene one\ntwo\nthree\nallora contiene tre righe, nessuna delle quali è vuota. Se un file di testo contiene one\ntwo\nthree, non si tratta di un file di testo, nello stesso senso in cui una frase senza un punto alla fine non è una frase.
Brandin,

Risposte:


217

Pensa ad alcuni dei problemi che possono verificarsi se non c'è una nuova riga. Secondo lo standard ANSI all'inizio #includedi un file inserisce il file esattamente com'è all'inizio del file e non inserisce la nuova riga #include <foo.h>dopo il contenuto del file. Quindi, se si include un file senza una nuova riga alla fine del parser, verrà visualizzato come se l'ultima riga di foo.hfosse sulla stessa riga della prima riga di foo.cpp. E se l'ultima riga di foo.h fosse un commento senza una nuova riga? Ora la prima riga di foo.cppè commentata. Questi sono solo un paio di esempi dei tipi di problemi che possono insinuarsi.


Volevo solo indicare alle parti interessate la risposta di James qui sotto. Mentre la risposta sopra è ancora corretta per C, il nuovo standard C ++ (C ++ 11) è stato modificato in modo che questo avviso non debba più essere emesso se si utilizza C ++ e un compilatore conforme a C ++ 11.

Dallo standard C ++ 11 tramite il post di James:

Un file di origine che non è vuoto e che non termina con un carattere di nuova riga o che termina con un carattere di nuova riga immediatamente preceduto da un carattere di barra rovesciata prima che avvenga una siffatta giunzione, deve essere elaborato come se un nuovo il carattere di linea è stato aggiunto al file (C ++ 11 §2.2 / 1).


28
Ovviamente in pratica ogni compilatore aggiunge una nuova riga dopo #include. Per fortuna.
mxcl,

3
Ricordo che una vecchia versione di Microsoft Visual C ++ (come 2.xo qualcosa del genere) aveva esattamente questo problema. È stato esacerbato perché l'editor IDE ha incoraggiato questo tipo di comportamento mancante di nuova riga.
Greg Hewgill,

2
I compilatori potrebbero non lamentarsi al momento, ma GitHub in realtà lo fa.
Puyover,

1
Vedo la risposta "sotto" di James ma: "La risposta sopra" in OrderBy what ?! Sopra c'è la domanda, come di solito ordino per voto. O intendi la tua risposta?
mbx,

@Thomas: questo programma evoca comportamenti indefiniti perché non termina con una nuova linea. Vedi programma qui: ideone.com/jswwf9
Distruttore

44

Il requisito che ogni file di origine terminasse con una nuova riga senza escape è stato rimosso in C ++ 11. La specifica ora recita:

Un file di origine che non è vuoto e che non termina con un carattere di nuova riga o che termina con un carattere di nuova riga immediatamente preceduto da un carattere di barra rovesciata prima che avvenga una siffatta giunzione, deve essere elaborato come se un nuovo il carattere di linea è stato aggiunto al file (C ++ 11 §2.2 / 1).

Un compilatore conforme non dovrebbe più emettere questo avviso (almeno non durante la compilazione in modalità C ++ 11, se il compilatore ha modalità per diverse revisioni delle specifiche del linguaggio).


4
Va tutto bene per C ++; sfortunatamente, C dice ancora che è UB, anche nell'ultima bozza del prossimo standard C1X.
Adam Rosenfield,

11
Questa domanda è taggata [c ++] e non [c].
James McNellis,

3
Anche così, probabilmente dovrebbe essere taggato [c], poiché molte persone che cercano questo avviso in C troveranno la loro strada qui.
Adam Rosenfield,

1
Questo è ancora un buon punto da aggiungere. Aggiungendo questo sopra. Spero non ti dispiaccia.
TJ Seabrooks,

25

La norma C ++ 03 [2.1.1.2] dichiara:

... Se un file di origine che non è vuoto non termina con un carattere di nuova riga o termina con un carattere di nuova riga immediatamente preceduto da un carattere barra rovesciata prima che si verifichi tale giunzione, il comportamento non è definito.


16

La risposta per "obbediente" è "perché lo standard C ++ 03 afferma che il comportamento di un programma che non termina con la nuova riga non è definito" (parafrasato).

La risposta per i curiosi è qui: http://gcc.gnu.org/ml/gcc/2001-07/msg01120.html .


4
Ah, l'amato "comportamento indefinito". Quando altre lingue falliscono, c / c ++ si comportano in modi "indefiniti" :) Questo, certamente, è una grande parte del loro fascino. E non sto scherzando.
Shylent,

6

Non si riferisce a una riga vuota, è se l'ultima riga (che può contenere contenuto) è terminata con una nuova riga.

La maggior parte degli editor di testo inserisce una nuova riga alla fine dell'ultima riga di un file, quindi se l'ultima riga non ne ha una, esiste il rischio che il file sia stato troncato. Tuttavia, ci sono validi motivi per cui potresti non voler la nuova riga, quindi è solo un avvertimento, non un errore.


5

#includesostituirà la sua riga con il contenuto letterale del file. Se il file non termina con una nuova riga, la riga che contiene quella #includeche l'ha estratta si unirà alla riga successiva.


2

Sto usando c-free IDE versione 5.0, nel mio programma del linguaggio 'c ++' o 'c' stavo avendo lo stesso problema. Alla fine del programma, ovvero l'ultima riga del programma (dopo parentesi graffe di funzione potrebbe essere principale o qualsiasi altra funzione), premere invio -line n. verrà aumentato di 1. quindi eseguire lo stesso programma, verrà eseguito senza errori.


2

Ovviamente in pratica ogni compilatore aggiunge una nuova riga dopo #include. Per fortuna. - @mxcl

non specifico C / C ++ ma un dialetto C: quando si usa il GL_ARB_shading_language_include estensione il compilatore glsl su OS X NON avvisa di una nuova riga mancante. Quindi puoi scrivere un MyHeader.hfile con una protezione dell'intestazione che termina con #endif // __MY_HEADER_H__e perderai sicuramente la linea dopo il #include "MyHeader.h".


2

Perché il comportamento differisce tra le versioni C / C ++ se il file non termina con la nuova riga. Soprattutto brutto è il vecchio C ++ - versioni, fx in C ++ 03 lo standard dice (fasi di traduzione):

Se un file di origine che non è vuoto non termina con un carattere di nuova riga o termina con un carattere di nuova riga immediatamente preceduto da un carattere barra rovesciata, il comportamento non è definito.

Il comportamento indefinito è negativo: un compilatore conforme standard potrebbe fare più o meno ciò che vuole qui (inserire un codice dannoso o altro) - chiaramente un motivo di avvertimento.

Mentre la situazione è migliore in C ++ 11, è una buona idea evitare situazioni in cui il comportamento non è definito nelle versioni precedenti. La specifica C ++ 03 è peggiore di C99 che proibisce completamente tali file (il comportamento viene quindi definito).


Sospetto che lo Standard abbia affermato che i programmi senza la nuova riga finale hanno un comportamento indefinito, piuttosto che dichiarare che erano mal formati, perché alcuni compilatori avrebbero concatenato una riga finale non terminata di un file incluso con il testo del codice sorgente in base alla #includedirettiva e alcuni programmatori che prendono di mira tali compilatori potrebbero aver sfruttato tale comportamento. Far sì che lo Standard lasci tali cose indefinite consentirebbe ai programmi che sfruttano tali stranezze di essere ben definiti su piattaforme che specificano tale comportamento. Avere un mandato standard comporterebbe la rottura di tali programmi.
supercat,

0

Questo avviso potrebbe anche aiutare a indicare che un file potrebbe essere stato troncato in qualche modo. È vero che il compilatore probabilmente genererà comunque un errore del compilatore - specialmente se si trova nel mezzo di una funzione - o forse un errore del linker, ma questi potrebbero essere più criptici e non si garantisce che si verifichino.

Ovviamente anche questo avviso non è garantito se il file viene troncato immediatamente dopo una nuova riga, ma potrebbe comunque rilevare alcuni casi in cui potrebbero mancare altri errori e dare un suggerimento più forte al problema.


-2

Questo non è un errore. È solo un avvertimento.

Apri il file in un editor, vai all'ultima riga del file e premi invio per aggiungere una riga vuota alla fine del file.

Tuttavia, oltre a ciò, dovresti usare #include <iostream>invece di <iostream.h>. Quindi inseriscilo using std::cout;dopo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.