「ファイルの終わりに改行がありません」というコンパイラ警告
-
09-06-2019 - |
質問
一部の C++ コンパイラで次の警告が表示される理由は何ですか?
ファイルの末尾に改行はありません
ソース/ヘッダー ファイルの最後に空の行が必要なのはなぜですか?
解決
改行がない場合に発生する可能性のある問題をいくつか考えてみましょう。ANSI 規格によれば、 #include
ファイルの先頭にファイルをそのまま挿入し、ファイルの後に改行を挿入しません。 #include <foo.h>
ファイルの内容の後に。したがって、末尾に改行のないファイルをパーサーに含めると、ファイルは次の行の最後の行であるかのように表示されます。 foo.h
の最初の行と同じ行にあります foo.cpp
. 。foo.h の最後の行が改行のないコメントだったらどうなるでしょうか?さて、最初の行は、 foo.cpp
はコメントアウトされています。これらは、忍び寄る可能性のある問題の種類のほんの一例です。
関係者に以下の James の回答を参照してもらいたかっただけです。上記の答えは C では依然として正しいですが、新しい C++ 標準 (C++11) は変更され、C++ と C++11 に準拠するコンパイラを使用している場合にはこの警告が発行されなくなりました。
James の投稿による C++11 標準から:
空ではなく、改行文字で終わっていないソース ファイル、またはそのようなスプライシングが行われる前にバックスラッシュ文字の直前にある改行文字で終わっているソース ファイルは、追加の改行文字であるかのように処理されます。行文字がファイルに追加されました (C++11 §2.2/1)。
他のヒント
すべてのソース ファイルがエスケープされていない改行で終わるという要件は、C++11 では削除されました。現在の仕様は次のようになります。
空ではなく、改行文字で終わっていないソース ファイル、またはそのようなスプライシングが行われる前にバックスラッシュ文字の直前にある改行文字で終わっているソース ファイルは、追加の改行文字であるかのように処理されます。行文字がファイルに追加されました (C++11 §2.2/1)。
準拠するコンパイラーは、この警告を発行しなくなりました (少なくとも、コンパイラーが言語仕様のさまざまなリビジョンに対応するモードを備えている場合、C++11 モードでコンパイルするときは発行されません)。
C++03 標準 [2.1.1.2] は次のように宣言しています。
...空でないソースファイルが、新しいライン文字で終了しない、またはそのようなスプライシングが行われる前にバックスラッシュ文字が直前に新しいライン文字で終了する場合、動作は未定義です。
「従順」の答えは、「C++03 標準では、改行で終わらないプログラムの動作は未定義であると規定されているからです」(意訳) です。
好奇心旺盛な人への答えは次のとおりです。 http://gcc.gnu.org/ml/gcc/2001-07/msg01120.html.
これは空行を参照しているのではなく、最後の行 (内容が含まれる可能性がある) が改行で終了しているかどうかです。
ほとんどのテキスト エディタではファイルの最終行の末尾に改行が挿入されるため、最終行に改行が含まれていない場合、ファイルが切り詰められる危険性があります。ただし、改行を使用したくない正当な理由があるため、これは単なる警告であり、エラーではありません。
#include
その行をファイルのリテラルの内容に置き換えます。ファイルが改行で終わっていない場合、 #include
それを取り込んだものは次の行とマージされます。
私は C フリー IDE バージョン 5.0 を使用しています。私のプログラムでは「C++」または「C」言語のいずれかで同じ問題が発生しました。 プログラムの最後に つまりプログラムの最後の行 (関数の中括弧の後は main 関数または任意の関数になる可能性があります)、Enterを押してください-行番号1 ずつ増加します。その後、同じプログラムを実行すると、エラーなしで実行されます。
もちろん、実際には、すべてのコンパイラが #include の後に新しい行を追加します。ありがたいことに。– @mxcl
特定の C/C++ ではなく、C 言語です。を使用するとき GL_ARB_shading_language_include
OS X の glsl コンパイラが拡張子を警告する ない 改行の欠落について。したがって、次のように書くことができます MyHeader.h
次で終わるヘッダー ガードを持つファイル #endif // __MY_HEADER_H__
あなたも 意思 の後にラインを失います #include "MyHeader.h"
確かに。
ファイルが改行で終わっていない場合、C/C++ のバージョンによって動作が異なるためです。特に厄介なのは、古い C++ バージョンです。C++ 03 の標準では次のように述べられています (変換フェーズ)。
空でないソースファイルが、新しいライン文字で終了しない、またはバックスラッシュ文字が直前に新しいライン文字で終了する場合、動作は未定義です。
未定義の動作は悪いです:標準に準拠したコンパイラは、多かれ少なかれ、ここで望むこと (悪意のあるコードなどを挿入する) を実行する可能性があり、これは明らかに警告の理由です。
C++11 では状況は改善されていますが、以前のバージョンで動作が定義されていない状況は避けることをお勧めします。C++03 仕様は、そのようなファイルを完全に禁止する C99 よりも劣っています (動作はその後定義されます)。
この警告は、ファイルが何らかの理由で切り詰められた可能性があることを示すのにも役立ちます。確かに、コンパイラはおそらくコンパイラ エラー (特に関数の途中にある場合) をスローするでしょう。あるいはおそらくリンカー エラーをスローします。しかし、これらはより不可解な可能性があり、必ず発生するという保証はありません。
もちろん、この警告は、ファイルが改行の直後で切り詰められている場合にも保証されませんが、他のエラーが見逃す可能性のあるいくつかのケースを検出する可能性があり、問題に対するより強力なヒントを提供します。
それは間違いではありません。それは単なる警告です。
エディタでファイルを開き、ファイルの最後の行に移動し、Enter キーを押してファイルの末尾に空白行を追加します。
ただし、それ以外に、次を使用する必要があります #include <iostream>
の代わりに <iostream.h>
. 。次に、 using std::cout;
その後。