it-swarm-vi.tech

Cảnh báo trình biên dịch "Không có dòng mới ở cuối tập tin"

Lý do cảnh báo sau trong một số trình biên dịch C++ là gì?

Không có dòng mới ở cuối tệp

Tại sao tôi phải có một dòng trống ở cuối tệp nguồn/tiêu đề?

180
LeChuck2k

Hãy nghĩ về một số vấn đề có thể xảy ra nếu không có dòng mới. Theo tiêu chuẩn ANSI, #include của một tệp ở đầu chèn tệp chính xác như ở mặt trước của tệp và không chèn dòng mới sau #include <foo.h> sau nội dung của tệp . Vì vậy, nếu bạn bao gồm một tệp không có dòng mới ở cuối trình phân tích cú pháp, nó sẽ được xem như là dòng cuối cùng của foo.h nằm trên cùng dòng với dòng đầu tiên của foo.cpp. Điều gì sẽ xảy ra nếu dòng cuối cùng của foo.h là một bình luận không có dòng mới? Bây giờ dòng đầu tiên của foo.cpp đã được nhận xét. Đây chỉ là một vài ví dụ về các loại vấn đề có thể leo lên.


Chỉ muốn chỉ ra bất kỳ bên quan tâm đến câu trả lời của James dưới đây. Mặc dù câu trả lời trên vẫn đúng với C, nhưng tiêu chuẩn C++ mới (C++ 11) đã được thay đổi để cảnh báo này không còn được đưa ra nếu sử dụng C++ và trình biên dịch tuân thủ C++ 11.

Từ tiêu chuẩn C++ 11 qua bài đăng của James:

Một tệp nguồn không trống và không kết thúc bằng một ký tự dòng mới hoặc kết thúc bằng một ký tự dòng mới ngay trước ký tự dấu gạch chéo ngược trước khi xảy ra bất kỳ sự ghép nối nào như vậy, sẽ được xử lý như thể một bổ sung mới ký tự dòng được thêm vào tệp (C++ 11 §2.2/1).

210
TJ Seabrooks

Yêu cầu rằng mọi tệp nguồn kết thúc bằng một dòng mới không thoát được loại bỏ trong C++ 11. Các đặc điểm kỹ thuật hiện đọc:

Một tệp nguồn không trống và không kết thúc bằng một ký tự dòng mới hoặc kết thúc bằng một ký tự dòng mới ngay trước ký tự dấu gạch chéo ngược trước khi xảy ra bất kỳ sự ghép nối nào như vậy, sẽ được xử lý như thể một phần mới bổ sung ký tự dòng được thêm vào tệp (C++ 11 §2.2/1).

Trình biên dịch tuân thủ sẽ không còn đưa ra cảnh báo này nữa (ít nhất là không khi biên dịch ở chế độ C++ 11, nếu trình biên dịch có các chế độ cho các phiên bản khác nhau của đặc tả ngôn ngữ).

42
James McNellis

Tiêu chuẩn C++ 03 [2.1.1.2] tuyên bố:

... Nếu một tệp nguồn không trống không kết thúc bằng ký tự dòng mới hoặc kết thúc bằng ký tự dòng mới ngay trước ký tự dấu gạch chéo ngược trước khi xảy ra bất kỳ kết nối nào như vậy, hành vi không được xác định.

24
Igor Semenov

Câu trả lời cho "vâng lời" là "bởi vì Tiêu chuẩn C++ 03 nói rằng hành vi của một chương trình không kết thúc trong dòng mới là không xác định" (diễn giải).

Câu trả lời cho sự tò mò là ở đây: http://gcc.gnu.org/ml/gcc/2001-07/msg01120.html .

15
Vytautas Shaltenis

Nó không đề cập đến một dòng trống, đó là liệu dòng cuối cùng (có thể có nội dung trong đó) được kết thúc bằng một dòng mới.

Hầu hết các trình soạn thảo văn bản sẽ đặt một dòng mới ở cuối dòng cuối cùng của tệp, vì vậy nếu dòng cuối cùng không có, có nguy cơ tệp bị cắt ngắn. Tuy nhiên, có những lý do hợp lệ tại sao bạn có thể không muốn dòng mới vì vậy nó chỉ là một cảnh báo, không phải là một lỗi.

6
Leigh Caldwell

#include sẽ thay thế dòng của nó bằng nội dung bằng chữ của tệp. Nếu tệp không kết thúc bằng một dòng mới, dòng chứa #include đã kéo nó vào sẽ hợp nhất với dòng tiếp theo.

5
moonshadow

Tất nhiên trong thực tế, mọi trình biên dịch đều thêm một dòng mới sau #include. Rất may. - @mxcl

không phải C/C++ cụ thể mà là một phương ngữ C: khi sử dụng phần mở rộng GL_ARB_shading_language_include, trình biên dịch glsl trên OS X cảnh báo bạn KHÔNG về một dòng mới bị thiếu. Vì vậy, bạn có thể viết tệp MyHeader.h với bộ bảo vệ tiêu đề kết thúc bằng #endif // __MY_HEADER_H__ và bạn sẽ mất dòng sau #include "MyHeader.h" chắc chắn.

2
Jan-Philip Loos

Bởi vì hành vi khác nhau giữa các phiên bản C/C++ nếu tệp không kết thúc bằng dòng mới. Đặc biệt khó chịu là C++ cũ hơn - phiên bản, fx trong C++ 03 tiêu chuẩn nói (giai đoạn dịch):

Nếu một tệp nguồn không trống không kết thúc bằng ký tự dòng mới hoặc kết thúc bằng ký tự dòng mới ngay trước ký tự dấu gạch chéo ngược, hành vi không được xác định.

Hành vi không xác định là xấu: một trình biên dịch tuân thủ tiêu chuẩn có thể thực hiện ít nhiều những gì nó muốn ở đây (chèn mã độc hại hoặc bất cứ điều gì) - rõ ràng là một lý do để cảnh báo.

Mặc dù tình hình tốt hơn trong C++ 11, một ý tưởng tốt là tránh các tình huống mà hành vi không được xác định trong các phiên bản trước. Đặc tả C++ 03 kém hơn C99, hoàn toàn cấm các tệp đó (hành vi được xác định sau đó).

2
skyking

Tôi đang sử dụng c-free IDE phiên bản 5.0, trong ngôn ngữ của tôi là ngôn ngữ 'c ++' hoặc 'c' tôi gặp vấn đề tương tự. Chỉ cần ở cuối chương trình tức là dòng cuối cùng của chương trình (sau dấu ngoặc của hàm, nó có thể là hàm chính hoặc bất kỳ hàm nào), nhấn enter - dòng số. sẽ được tăng thêm 1. sau đó thực hiện cùng một chương trình, nó sẽ chạy mà không gặp lỗi.

2
divesh

Cảnh báo này cũng có thể giúp chỉ ra rằng một tệp có thể đã bị cắt bớt bằng cách nào đó. Đúng là trình biên dịch có thể sẽ gây ra lỗi trình biên dịch - đặc biệt là nếu nó ở giữa hàm - hoặc có thể là lỗi liên kết, nhưng những lỗi này có thể khó hiểu hơn và không được đảm bảo xảy ra.

Tất nhiên cảnh báo này cũng không được đảm bảo nếu tệp bị cắt ngay lập tức sau một dòng mới, nhưng nó vẫn có thể bắt được một số trường hợp mà các lỗi khác có thể bỏ lỡ và đưa ra gợi ý mạnh mẽ hơn cho vấn đề.

0
mwfearnley