「ファイルの終わりに改行がない」コンパイラの警告


187

一部のC ++コンパイラで次の警告が出る理由は何ですか?

ファイルの終わりに改行なし

ソース/ヘッダーファイルの最後に空の行が必要なのはなぜですか?


17
そうでもない理由は、それはあなたであれば非常に迷惑なんだcatファイルおよびプロンプトの新しいシェルは、ファイルの最後の行の後に表示されるように、(いない列0にすなわち)末尾の改行を持っていない
ThiefMaster

@ThiefMaster私の$ PS1は、まさにその理由で改行で始まります。(とにかく、それは複数行のプロンプトであり、1行に
一連

7
Why should I have an empty line at the end of a source/header file-テキストファイルにone\ntwo\nthree\n3行が含まれている場合、空の行はありません。テキストファイルが含まれている場合、one\ntwo\nthreeそれはテキストファイルではありません。つまり、最後に完全な停止がない文は文ではありません。
ブランディン2014年

回答:


217

改行がない場合に発生する可能性のある問題について考えてみます。ANSI規格によれば#include、最初のファイルはファイルの先頭にそのまま挿入され、ファイル#include <foo.h>の内容の後の後に新しい行は挿入されません。したがって、パーサーの最後に改行のないファイルを含めると、の最後の行がfoo.hの最初の行と同じ行にあるかのように表示されfoo.cppます。foo.hの最後の行が改行のないコメントだった場合はどうなりますか?の最初の行foo.cppがコメント化されました。これらは、忍び寄る可能性がある問題のタイプのほんの数例です。


以下のジェームズの回答を関係者に指摘したかっただけです。上記の回答はCでも正しいですが、新しいC ++標準(C ++ 11)が変更されたため、C ++およびC ++ 11に準拠したコンパイラーを使用している場合にこの警告が発行されなくなりました。

Jamesの投稿によるC ++ 11標準から:

空ではなく、改行文字で終了しない、またはそのようなスプライシングが行われる前にバックスラッシュ文字の直前に改行文字で終了するソースファイルは、追加のnew-行文字がファイルに追加されました(C ++ 11§2.2/ 1)。


28
もちろん実際には、すべてのコンパイラーが#includeの後に新しい行を追加します。ありがたいことに。
mxcl 2008年

3
Microsoft Visual C ++の古いバージョン(2.xなど)がまさにこの問題を抱えていたことを思い出します。IDEエディターがこの種の改行の欠落動作を奨励したため、事態はさらに悪化しました。
グレッグ・ヒューギル

2
現在、コンパイラは文句を言わないかもしれませんが、GitHubは実際に文句を言います。
Puyover 2013

1
ジェームズの「以下」の回答は表示されますが、上記の回答」はOrderByで何ですか。上記は質問です。私は通常投票で注文します。それともあなた自身の答えですか?
mbx 14

@Thomas:このプログラムは改行で終わらないため、未定義の動作を呼び出しますか?ここにプログラムを参照してください:ideone.com/jswwf9
デストラクタ

44

すべてのソースファイルがエスケープされていない改行で終わるという要件は、C ++ 11で削除されました。仕様は次のようになります。

空ではなく、改行文字で終了しない、またはそのようなスプライシングが行われる前にバックスラッシュ文字の直前に改行文字で終了するソースファイルは、追加のnew-行文字がファイルに追加されました(C ++ 11§2.2/ 1)。

適合コンパイラは、この警告を発行しなくなりました(少なくとも、コンパイラに言語仕様の異なるリビジョンのモードがある場合、C ++ 11モードでコンパイルするときは)。


4
C ++にとってはそれで十分です。残念ながら、CはそれがUBであるとまだ言っています、次のC1X標準の最新のドラフトでも。
Adam Rosenfield

11
この質問には[c]ではなく[c ++]のタグが付けられています。
James McNellis、2011年

3
それでも、おそらくCでタグ付けする必要があります。Cでこの警告を検索する多くの人々は、ここで道を見つけるでしょう。
Adam Rosenfield

1
これはまだ追加するのに良いポイントです。これを上に追加します。よろしくお願いします。
TJシーブルックス

25

C ++ 03標準[2.1.1.2]は以下を宣言します:

...空でないソースファイルが改行文字で終わっていない場合、またはそのようなスプライシングが行われる前にバックスラッシュ文字の直前にある改行文字で終わっている場合、動作は未定義です。


16

「従順」の答えは、「C ++ 03標準では改行で終わらないプログラムの動作は定義されていないため」(言い換え)です。

好奇心が強い人のための答えはここにあります:http : //gcc.gnu.org/ml/gcc/2001-07/msg01120.html


4
ああ、愛される「未定義の行動」。他の言語が失敗すると、c / c ++は「未定義」の方法で動作します:)それは確かに、彼らの魅力の大部分です。そして、私は冗談ではありません。
2010年

6

それは空白行を参照しているのではなく、最後の行(コンテンツを含めることができる)が改行で終了しているかどうかです。

ほとんどのテキストエディタでは、ファイルの最後の行の終わりに改行が挿入されるため、最後の行に改行がない場合、ファイルが切り捨てられるリスクがあります。ただし、改行が不要になる正当な理由があるため、これは単なる警告であり、エラーではありません。


5

#includeその行をファイルのリテラル内容で置き換えます。ファイルが改行で終わっていない場合、#includeそれをプルしたを含む行は次の行とマージされます。


2

私はc-free IDEバージョン5.0を使用していますが、 'c ++'または 'c'言語のどちらのプログラムでも同じ問題が発生していましたプログラムの最後つまりプログラムの最後の行(関数のブレースの後)メインまたは任意の関数)、Enterキーを押します-行番号。1.増加し、同じプログラムを実行すると、エラーなしで実行されます。


2

もちろん実際には、すべてのコンパイラーが#includeの後に新しい行を追加します。ありがたいことに。– @mxcl

特定のC / C ++ではなくC方言:GL_ARB_shading_language_include拡張機能を使用する場合、OS Xのglslコンパイラは改行がないことについて警告します。そのため、MyHeader.h末尾がであるヘッダーガードを使用してファイルを書き込むことができ、確実にの後の行失い#endif // __MY_HEADER_H__ます。#include "MyHeader.h"


2

ファイルが改行で終わっていない場合、C / C ++バージョン間で動作が異なるためです。特に厄介なのは、古いC ++バージョンです。C++ 03のfxでは、標準に次のように記載されています(翻訳段階)

空でないソースファイルが改行文字で終わっていない場合、またはバックスラッシュ文字の直前にある改行文字で終わっている場合、動作は未定義です。

未定義の動作は悪いです。標準に準拠するコンパイラは、ここで何をしたいか(悪意のあるコードなどを挿入)を実行できます。

C ++ 11では状況が改善されていますが、以前のバージョンでは動作が定義されていない状況を回避することをお勧めします。C ++ 03仕様は、そのようなファイルを完全に禁止するC99よりも悪いものです(動作が定義されています)。


一部のコンパイラは、インクルードされたファイルの終端されていない最終行を、#includeディレクティブに続くソースコードテキストと連結するため、改行のないプログラムには未定義の動作があると標準が言っているのではないかと思います、およびそのようなコンパイラを対象とする一部のプログラマは、そのような動作を悪用した可能性があります。標準にそのようなものを未定義のままにしておくと、そのような癖を悪用するプログラムを、そのような動作を指定するプラットフォームで明確に定義できます。標準に義務を課すと、そのようなプログラムは動作しなくなります。
スーパーキャット2015

0

この警告は、ファイルが何らかの理由で切り捨てられた可能性があることを示す場合にも役立ちます。とにかく、コンパイラがコンパイラエラーをスローするのは事実です-特にそれが関数の途中にある場合-またはおそらくリンカエラーですが、これらはより不可解である可能性があり、発生が保証されていません。

もちろん、この警告は、改行の直後にファイルが切り捨てられた場合も保証されませんが、他のエラーが見落とす可能性のあるいくつかのケースをキャッチし、問題に対するより強力なヒントを提供します。


-2

エラーではありません。これは単なる警告です。

エディターでファイルを開き、ファイルの最後の行に移動し、Enterキーを押して、ファイルの最後に空白行を追加します。

ただし、それ以外に、の#include <iostream>代わりに使用する必要があり<iostream.h>ます。その後に入れusing std::cout;ます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.