Попередження компілятора "Немає нового рядка в кінці файлу"


187

У чому причина наступного попередження у деяких компіляторах C ++?

Немає нового рядка в кінці файлу

Чому я повинен мати порожній рядок у кінці файлу джерела / заголовка?


17
Насправді це не причина, але це дуже дратує, якщо ви маєте catфайл, і він не має зворотного нового рядка, оскільки новий запит оболонки з’явиться після останнього рядка файлу (тобто не у стовпці 0)
ThiefMaster

@TentistMaster Мій $ PS1 починається з нової лінії саме з цієї причини. (це все одно багато рядкове підказка, що містить купу корисної інформації в одному рядку, а потім нічого, окрім підказкового символу на наступному, щоб досить довгі команди не загорталися)
bames53

7
Why should I have an empty line at the end of a source/header file- Якщо текстовий файл містить, one\ntwo\nthree\nто він містить три рядки, жоден з яких не порожній. Якщо текстовий файл містить, one\ntwo\nthreeто це не текстовий файл, в тому ж сенсі, що речення без повної зупинки в кінці не є реченням.
Брандін

Відповіді:


217

Придумайте деякі проблеми, які можуть виникнути, якщо немає нового рядка. Відповідно до стандарту ANSI, #includeфайл на початку вставляє файл точно так само, як на передній частині файлу, і не вставляє новий рядок після #include <foo.h>вмісту файлу після. Отже, якщо ви включите файл без нового рядка в кінці до аналізатора, він буде розглядатись так, ніби останній рядок foo.hзнаходиться в тому ж рядку, що і перший рядок foo.cpp. Що робити, якщо останній рядок foo.h був коментарем без нового рядка? Тепер перший рядок foo.cppкоментується. Це лише кілька прикладів типів проблем, які можуть повстати.


Просто хотів вказати будь-яким зацікавленим сторонам на відповідь Джеймса нижче. Хоча вищезазначена відповідь все ще правильна для C, новий стандарт C ++ (C ++ 11) був змінений, так що це попередження більше не повинно видаватися, якщо використовується C ++ та компілятор, що відповідає C ++ 11.

З C ++ 11 стандартних через повідомлення Джеймса:

Вихідний файл, який не є порожнім і не закінчується символом нового рядка, або який закінчується символом нового рядка, що безпосередньо передує символу зворотної косої риски перед тим, як відбудеться таке сплайсування, обробляється так, ніби додатковий новий символьний рядок був доданий до файлу (C ++ 11 §2.2 / 1).


28
Звичайно, на практиці кожен компілятор додає новий рядок після #include. Вдячно
mxcl

3
Пригадую, у старій версії Microsoft Visual C ++ (на кшталт 2.x або щось подібне) була саме така проблема. Це було ще більше загострене, оскільки редактор IDE заохочував подібну поведінку відсутнього нового рядка.
Грег Хьюгілл

2
Наразі компілятори можуть не скаржитися, але GitHub насправді так робить.
Пуйовер

1
Я можу побачити відповідь Джеймса "нижче", але: "Наведена вище відповідь" у OrderBy що ?! Вище це питання, як я зазвичай замовляю голосами. Або ти маєш на увазі свою власну відповідь?
mbx

@Thomas: Ця програма викликає невизначене поведінку, оскільки вона не закінчується новим рядком. Дивіться програму тут: ideone.com/jswwf9
Destructor

44

Вимога про те, щоб кожен вихідний файл закінчувався новим рядком, що не вийшов, був видалений у C ++ 11. Тепер специфікація гласить:

Вихідний файл, який не є порожнім і не закінчується символом нового рядка, або який закінчується символом нового рядка, що безпосередньо передує символу зворотної косої риски перед тим, як відбудеться таке сплайсування, обробляється так, ніби додатковий новий символьний рядок був доданий до файлу (C ++ 11 §2.2 / 1).

Відповідний компілятор більше не повинен видавати це попередження (принаймні, не під час компіляції в режимі C ++ 11, якщо у компілятора є режими для різних модифікацій мовної специфікації).


4
Це все добре і добре для C ++; на жаль, C все ще каже, що це UB, навіть в останньому проекті майбутнього стандарту C1X.
Адам Розенфілд

11
Це питання позначено тегами [c ++], а не [c].
James McNellis

3
Незважаючи на це, це, мабуть, має бути позначено тегами [c], оскільки багато людей, які шукають це попередження в C, знайдуть тут свій шлях.
Адам Розенфілд

1
Це ще хороший момент для додання. Додавання цього вище. Сподіваюся, ви не заперечуєте.
TJ Seabrooks

25

Стандарт C ++ 03 [2.1.1.2] декларує:

... Якщо вихідний файл, який не є порожнім, не закінчується символом нового рядка або закінчується символом нового рядка, який безпосередньо передує символу зворотної косої риски перед тим, як відбудеться таке сплайсинг, поведінка не визначена.


16

Відповідь для "слухняних" - "тому, що стандарт C ++ 03 говорить, що поведінка програми, що не закінчується новим рядком, не визначена" (перефразовано).

Відповідь для допитливих тут: http://gcc.gnu.org/ml/gcc/2001-07/msg01120.html .


4
Ах, кохана "невизначена поведінка". Коли інші мови не вдається, c / c ++ поводяться "не визначеними" способами :) Це, безумовно, є великою частиною їх чарівності. І я не жартую.
шилент

6

Це не стосується порожнього рядка, це те, чи останній рядок (який може містити вміст у ньому) закінчується новим рядком.

Більшість текстових редакторів поміщають новий рядок в кінці останнього рядка файлу, тому якщо в останньому рядку його немає, є ризик, що файл був усічений. Однак є поважні причини, чому ви можете не хотіти нового рядка, тому це лише попередження, а не помилка.


5

#includeзамінить його рядок буквальним вмістом файлу. Якщо файл не закінчується новим рядком, рядок, що містить його #include, потягнув його, об'єднається з наступним рядком.


2

Я використовую c-free IDE версії 5.0, в моїй програмі будь-якої з 'c ++' або 'c' мови, у мене виникала така ж проблема. Просто в кінці програми, тобто в останньому рядку програми (після дужок функції це може бути основна або будь-яка функція), натисніть клавішу Enter -line no. буде збільшено на 1. після виконання тієї ж програми, вона запуститься без помилок.


2

Звичайно, на практиці кожен компілятор додає новий рядок після #include. Вдячно - @mxcl

не специфічний C / C ++, але діалект C: при використанні GL_ARB_shading_language_includeрозширення компілятор glsl в OS X попереджає НЕ про відсутній новий рядок. Таким чином , ви можете написати MyHeader.hфайл з охоронцем заголовка , який закінчується , #endif // __MY_HEADER_H__і ви будете втрачати лінію після того , як #include "MyHeader.h"точно.


2

Оскільки поведінка відрізняється між версіями C / C ++, якщо файл не закінчується новим рядком. Особливо неприємним є старіший C ++ - версії, fx в C ++ 03 стандарт говорить (етапи перекладу):

Якщо вихідний файл, який не є порожнім, не закінчується символом нового рядка або закінчується символом нового рядка, який безпосередньо передує символу зворотної косої риси, поведінка не визначена.

Невизначена поведінка погана: стандартний відповідний компілятор може робити більше або менше того, що хоче тут (вставити шкідливий код чи що завгодно) - очевидно, причина для попередження.

Хоча ситуація краща в C ++ 11, добре уникати ситуацій, коли поведінка не визначена в попередніх версіях. Специфікація C ++ 03 гірша, ніж C99, яка прямо забороняє такі файли (поведінка потім визначається).


Я підозрюю, що Стандарт сказав, що програми без останнього нового рядка мають не визначену поведінку, а не заявляють, що вони неправильно сформовані, тому що деякі компілятори об'єднали б не завершений остаточний рядок включеного файлу з текстом вихідного коду, що слідує #includeдирективі , а деякі програмісти, націлені на такі компілятори, можливо, використовували таку поведінку. Якщо Стандарт залишає такі речі не визначеними, це дозволить програмам, що використовують такі химерності, чітко визначитися на платформах, які визначають таку поведінку. Маючи мандат "Стандарт", поведінка порушила б такі програми.
supercat

0

Це попередження може також допомогти вказати, що файл міг бути якось усічений. Це правда, що компілятор, ймовірно, видасть помилку компілятора в будь-якому випадку - особливо, якщо він знаходиться в середині функції - або, можливо, помилка лінкера, але вони можуть бути більш криптовалютними і не гарантовано трапляться.

Звичайно, це застереження також не гарантується, якщо файл обрізається відразу після нового рядка, але він все одно може зафіксувати деякі випадки, які можуть бути пропущені іншими помилками, і дає більш сильний натяк на проблему.


-2

Це не помилка. Це просто попередження.

Відкрийте файл у редакторі, перейдіть до останнього рядка та натисніть клавішу Enter, щоб додати порожній рядок до кінця файла.

Хоча, крім цього, ви повинні використовувати #include <iostream>замість цього <iostream.h>. Потім покладіть в нього using std::cout;після.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.