Aviso do compilador "Nenhuma nova linha no final do arquivo"

187

Qual é o motivo do seguinte aviso em alguns compiladores C ++?

Nenhuma nova linha no final do arquivo

Por que eu deveria ter uma linha vazia no final de um arquivo de origem / cabeçalho?

Brian Tompsett - 汤 莱恩
fonte
17
Não é realmente a razão, mas é muito chato se você catum arquivo e ele não tem uma nova linha de fuga como o novo shell prompt aparecerá após a última linha do arquivo (ou seja, não na coluna 0)
ThiefMaster
@ThiefMaster Meu $ PS1 começa com uma nova linha por esse motivo. (é um multi linha de prompt de qualquer maneira, que contém um monte de informações úteis em uma linha e, em seguida, nada mais que um personagem pronto no próximo para que bastante longos comandos não envolvê)
bames53
7
Why should I have an empty line at the end of a source/header file- Se um arquivo de texto contém one\ntwo\nthree\n, ele contém três linhas, nenhuma das quais está vazia. Se um arquivo de texto contiver one\ntwo\nthree, ele não será um arquivo de texto, no mesmo sentido em que uma sentença sem ponto final no final não é uma sentença.
Brandin

Respostas:

217

Pense em alguns dos problemas que podem ocorrer se não houver nova linha. De acordo com o padrão ANSI, o #includede um arquivo no início insere o arquivo exatamente como está na frente do arquivo e não insere a nova linha #include <foo.h>após o conteúdo do arquivo. Portanto, se você incluir um arquivo sem nova linha no final do analisador, ele será exibido como se a última linha de estivesse foo.hna mesma linha que a primeira linha de foo.cpp. E se a última linha de foo.h fosse um comentário sem uma nova linha? Agora, a primeira linha de foo.cppé comentada. Estes são apenas alguns exemplos dos tipos de problemas que podem surgir.


Só queria apontar as partes interessadas para a resposta de James abaixo. Embora a resposta acima ainda esteja correta para C, o novo padrão C ++ (C ++ 11) foi alterado para que esse aviso não seja mais emitido se você estiver usando C ++ e um compilador em conformidade com C ++ 11.

Do padrão C ++ 11 via postagem de James:

Um arquivo de origem que não esteja vazio e que não termine com um caractere de nova linha, ou que termine com um caractere de nova linha imediatamente precedido por um caractere de barra invertida antes de qualquer emenda, deve ser processado como se fosse um novo o caractere de linha foi anexado ao arquivo (C ++ 11 §2.2 / 1).

TJ Seabrooks
fonte
28
Obviamente, na prática, todo compilador adiciona uma nova linha após o #include. Agradecidamente.
Mxcl 20/10/08
3
Lembro-me de que uma versão antiga do Microsoft Visual C ++ (como 2.x ou algo assim) tinha exatamente esse problema. Foi exacerbado porque o editor do IDE incentivou esse tipo de comportamento de falta de nova linha.
Greg Hewgill 12/11/2008
2
Os compiladores podem não se queixar atualmente, mas o GitHub realmente o faz.
Puyover
1
Eu posso ver a resposta "abaixo" de James, mas: "A resposta acima" em OrderBy what ?! Acima está a pergunta, como costumo pedir por votos. Ou você quer dizer sua própria resposta?
114414
@ Thomas: Este programa chama um comportamento indefinido porque não termina com uma nova linha. Veja o programa aqui: ideone.com/jswwf9
Destructor
44

O requisito de que todo arquivo de origem termine com uma nova linha não escapada foi removido no C ++ 11. A especificação agora diz:

Um arquivo de origem que não esteja vazio e que não termine com um caractere de nova linha, ou que termine com um caractere de nova linha imediatamente precedido por um caractere de barra invertida antes de qualquer emenda, deve ser processado como se fosse um novo o caractere de linha foi anexado ao arquivo (C ++ 11 §2.2 / 1).

Um compilador em conformidade não deve mais emitir esse aviso (pelo menos não ao compilar no modo C ++ 11, se o compilador tiver modos para diferentes revisões da especificação da linguagem).

James McNellis
fonte
4
Está tudo bem para C ++; infelizmente, C ainda diz que é UB, mesmo no último rascunho do próximo padrão C1X.
Adam Rosenfield
11
Esta pergunta está marcada com [c ++] e não [c].
James McNellis
3
Mesmo assim, provavelmente deve ser marcado [c], já que muitas pessoas que procuram esse aviso em C encontrarão o caminho para cá.
precisa
1
Este ainda é um bom ponto a acrescentar. Adicionando isso acima. Espero que você não se importe.
TJ Seabrooks
25

O padrão C ++ 03 [2.1.1.2] declara:

... Se um arquivo de origem que não estiver vazio não terminar em um caractere de nova linha, ou terminar em um caractere de nova linha imediatamente precedido por um caractere de barra invertida antes de qualquer emenda, o comportamento será indefinido.

Igor Semenov
fonte
16

A resposta para o "obediente" é "porque o Padrão C ++ 03 diz que o comportamento de um programa que não termina em nova linha é indefinido" (parafraseado).

A resposta para os curiosos está aqui: http://gcc.gnu.org/ml/gcc/2001-07/msg01120.html .

Vytautas Shaltenis
fonte
4
Ahh, o amado "comportamento indefinido". Quando outras linguagens falham, o c / c ++ se comporta de maneiras "indefinidas" :) Isso, certamente, é uma grande parte de seu charme. E eu não estou brincando.
shylent
6

Não se refere a uma linha em branco, é se a última linha (que pode conter conteúdo) é finalizada com uma nova linha.

A maioria dos editores de texto colocará uma nova linha no final da última linha de um arquivo; portanto, se a última linha não tiver uma, existe o risco de o arquivo ter sido truncado. No entanto, existem razões válidas pelas quais você pode não querer a nova linha; portanto, é apenas um aviso, não um erro.

Leigh Caldwell
fonte
5

#includesubstituirá sua linha pelo conteúdo literal do arquivo. Se o arquivo não terminar com uma nova linha, a linha contendo a #includeque o puxou entrará na próxima linha.

sombra da Lua
fonte
2

Eu estou usando c-livre IDE versão 5.0, na minha progrm qualquer um 'c ++' ou 'c' linguagem i estava ficando mesmo problem.Just no final do programa ou seja, última linha do programa (após chaves de função pode ser principal ou qualquer função), pressione enter - line no. será aumentado em 1.; em seguida, execute o mesmo programa, ele será executado sem erros.

divesh
fonte
2

Obviamente, na prática, todo compilador adiciona uma nova linha após o #include. Agradecidamente. - @mxcl

C / C ++ não específico, mas um dialeto C: ao usar a GL_ARB_shading_language_includeextensão, o compilador glsl no OS X avisa NÃO sobre uma nova linha ausente. Então você pode escrever um MyHeader.harquivo com um guarda cabeçalho que termina com #endif // __MY_HEADER_H__e você vai perder a linha após a #include "MyHeader.h"certeza.

Jan-Philip Loos
fonte
2

Porque o comportamento difere entre as versões C / C ++ se o arquivo não terminar com nova linha. Especialmente desagradável é as versões C ++ mais antigas, fx em C ++ 03, o padrão diz (fases de tradução):

Se um arquivo de origem que não estiver vazio não terminar em um caractere de nova linha ou terminar em um caractere de nova linha imediatamente precedido por um caractere de barra invertida, o comportamento será indefinido.

O comportamento indefinido é ruim: um compilador em conformidade padrão pode fazer mais ou menos o que deseja aqui (inserir código malicioso ou o que for) - claramente um motivo para aviso.

Embora a situação seja melhor no C ++ 11, é uma boa ideia evitar situações em que o comportamento é indefinido nas versões anteriores. A especificação C ++ 03 é pior que a C99, que proíbe completamente esses arquivos (o comportamento é então definido).

skyking
fonte
Suspeito que o Padrão tenha dito que os programas sem a nova linha à direita têm comportamento indefinido, em vez de afirmarem que estavam mal formados, porque alguns compiladores concatenariam uma linha final não terminada de um arquivo incluído com o texto do código fonte seguindo a #includediretiva , e alguns programadores direcionados a esses compiladores podem ter explorado esse comportamento. Se o Padrão deixar essas coisas como Indefinidas, os programas que exploram essas peculiaridades serão bem definidos em plataformas que especificam esse comportamento. Ter o Padrão como um comportamento quebraria esses programas.
Supercat
0

Esse aviso também pode ajudar a indicar que um arquivo pode ter sido truncado de alguma forma. É verdade que o compilador provavelmente lançará um erro do compilador de qualquer maneira - especialmente se estiver no meio de uma função - ou talvez um erro do vinculador, mas estes podem ser mais enigmáticos e não são garantidos.

É claro que esse aviso também não é garantido se o arquivo for truncado imediatamente após uma nova linha, mas ainda assim pode ser detectado alguns casos em que outros erros podem falhar e fornece uma dica mais forte para o problema.

mwfearnley
fonte
-2

Isso não é um erro. É apenas um aviso.

Abra o arquivo em um editor, vá para a última linha do arquivo e pressione Enter para adicionar uma linha em branco ao final do arquivo.

Embora, além disso, você deva estar usando em #include <iostream>vez de <iostream.h>. Em seguida, coloque um using std::cout;depois dele.

keya
fonte