คำเตือนคอมไพเลอร์“ ไม่มีบรรทัดใหม่ที่ท้ายไฟล์”


187

อะไรคือสาเหตุของคำเตือนต่อไปนี้ในคอมไพเลอร์ C ++ บางตัว?

ไม่มีการขึ้นบรรทัดใหม่ท้ายไฟล์

เหตุใดฉันจึงควรมีบรรทัดว่างท้ายไฟล์ต้นทาง / ส่วนหัว


17
ไม่ใช่เหตุผลจริงๆ แต่มันน่ารำคาญมากหากคุณcatไฟล์และไม่มี newline ต่อท้ายเนื่องจาก shell prompt ใหม่จะปรากฏขึ้นหลังจากบรรทัดสุดท้ายของไฟล์ (เช่นไม่ใช่ในคอลัมน์ 0)
ThiefMaster

@ThiefMaster ฉัน $ 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อยู่แสดงว่าไม่ใช่ไฟล์ข้อความในความหมายเดียวกันว่าประโยคที่ไม่มีการหยุดแบบเต็มตอนท้ายนั้นไม่ใช่ประโยค
Brandin

คำตอบ:


217

นึกถึงปัญหาที่อาจเกิดขึ้นได้หากไม่มีการขึ้นบรรทัดใหม่ ตามมาตรฐาน ANSI #includeของไฟล์ที่จุดเริ่มต้นแทรกไฟล์ตรงกับที่อยู่ด้านหน้าของไฟล์และไม่แทรกบรรทัดใหม่#include <foo.h>หลังจากเนื้อหาของไฟล์ ดังนั้นถ้าคุณรวมถึงไฟล์ที่มีการขึ้นบรรทัดใหม่ไม่มีที่สิ้นสุดในการแยกวิเคราะห์ก็จะถูกมองว่าเป็นถ้าบรรทัดสุดท้ายของที่อยู่ในสายเดียวกันกับบรรทัดแรกของfoo.h foo.cppเกิดอะไรขึ้นถ้าบรรทัดสุดท้ายของ foo.h เป็นความคิดเห็นที่ไม่มีบรรทัดใหม่ ตอนนี้บรรทัดแรกของfoo.cppความเห็นออก เหล่านี้เป็นเพียงตัวอย่างของปัญหาที่สามารถคืบคลานขึ้นมาได้


แค่ต้องการชี้ผู้ที่สนใจให้ตอบคำถามของเจมส์ด้านล่าง ในขณะที่คำตอบข้างต้นยังคงถูกต้องสำหรับ C มาตรฐาน C ++ ใหม่ (C ++ 11) ได้รับการเปลี่ยนแปลงเพื่อไม่ให้มีการออกคำเตือนนี้อีกต่อไปหากใช้ C ++ และคอมไพเลอร์ที่สอดคล้องกับ C ++ 11

จากมาตรฐาน C ++ 11 ผ่านทางโพสต์ของ James:

ไฟล์ต้นฉบับที่ไม่ว่างเปล่าและไม่ได้ลงท้ายด้วยอักขระขึ้นบรรทัดใหม่หรือที่ลงท้ายด้วยอักขระขึ้นบรรทัดใหม่นำหน้าด้วยอักขระแบ็กสแลชในทันทีก่อนที่จะมีการประกบใด ๆ เกิดขึ้นราวกับว่ามีการเพิ่มใหม่ อักขระบรรทัดถูกผนวกเข้ากับไฟล์ (C ++ 11 §2.2 / 1)


28
แน่นอนว่าในทางปฏิบัติคอมไพเลอร์ทุกตัวจะเพิ่มบรรทัดใหม่หลังจาก #include ขอบคุณ
mxcl

3
ฉันจำ Microsoft Visual C ++ รุ่นเก่า (เช่น 2.x หรืออะไรบางอย่าง) มีปัญหาตรงนี้ มันถูกทำให้รุนแรงขึ้นเนื่องจากตัวแก้ไข IDE สนับสนุนการทำงานแบบใหม่ที่ขาดหายไป
เกร็กฮิวกิลล์

2
คอมไพเลอร์อาจไม่บ่นในขณะนี้ แต่ GitHub ทำเช่นนั้น
Puyover

1
ฉันเห็นคำตอบของ "ด้านล่าง" โดยเจมส์แต่: "คำตอบข้างบน" ใน OrderBy คืออะไร! ข้างต้นเป็นคำถามที่ฉันมักจะสั่งซื้อด้วยคะแนนเสียง หรือคุณหมายถึงคำตอบของคุณเอง?
mbx

@Thomas: เป็นโปรแกรมที่เรียกใช้พฤติกรรมที่ไม่ได้กำหนดเพราะมันไม่ได้จบลงด้วยการขึ้นบรรทัดใหม่ ดูโปรแกรมได้ที่นี่: ideone.com/jswwf9
Destructor

44

ข้อกำหนดที่ทุกไฟล์ต้นฉบับสิ้นสุดด้วยการขึ้นบรรทัดใหม่ที่ไม่หนีถูกลบใน C ++ 11 ข้อมูลจำเพาะตอนนี้อ่าน:

ไฟล์ต้นฉบับที่ไม่ว่างเปล่าและไม่ได้ลงท้ายด้วยอักขระขึ้นบรรทัดใหม่หรือที่ลงท้ายด้วยอักขระขึ้นบรรทัดใหม่นำหน้าด้วยอักขระแบ็กสแลชในทันทีก่อนที่จะมีการประกบใด ๆ เกิดขึ้นราวกับว่ามีการเพิ่มใหม่ อักขระบรรทัดถูกผนวกเข้ากับไฟล์ (C ++ 11 §2.2 / 1)

คอมไพเลอร์ที่สอดคล้องไม่ควรออกคำเตือนนี้อีกต่อไป (อย่างน้อยก็ไม่ใช่เมื่อรวบรวมในโหมด C ++ 11 หากคอมไพเลอร์มีโหมดสำหรับการแก้ไขข้อกำหนดภาษาที่แตกต่างกัน)


4
นั่นคือทั้งหมดที่ดีและดีสำหรับ C ++; น่าเสียดายที่ C ยังคงกล่าวว่าเป็น UB แม้จะอยู่ในร่างล่าสุดของมาตรฐาน C1X ที่กำลังจะมาถึง
Adam Rosenfield

11
คำถามนี้ถูกแท็ก [c ++] ไม่ใช่ [c]
James McNellis

3
ถึงกระนั้นก็ควรติดแท็ก [c] เนื่องจากหลายคนค้นหาคำเตือนนี้ใน C จะหาทางของพวกเขาที่นี่
Adam Rosenfield

1
ยังคงเป็นจุดที่ดีที่จะเพิ่ม เพิ่มขึ้นด้านบน หวังว่าคุณจะไม่รังเกียจ
TJ Seabrooks

25

C ++ 03 Standard [2.1.1.2] ประกาศ:

... หากไฟล์ต้นฉบับที่ไม่ว่างเปล่าไม่ได้ลงท้ายด้วยอักขระขึ้นบรรทัดใหม่หรือลงท้ายด้วยอักขระขึ้นบรรทัดใหม่นำหน้าด้วยอักขระแบ็กสแลชในทันทีก่อนที่จะมีการประกบใด ๆ ลักษณะการทำงานจะไม่ได้กำหนดไว้


16

คำตอบสำหรับ "เชื่อฟัง" คือ "เพราะมาตรฐาน C ++ 03 บอกพฤติกรรมของโปรแกรมที่ไม่ได้ลงท้ายด้วยการขึ้นบรรทัดใหม่จะไม่ได้กำหนด" (ถอดความ)

คำตอบสำหรับการอยากรู้อยากเห็นอยู่ที่นี่: http://gcc.gnu.org/ml/gcc/2001-07/msg01120.html


4
Ahh ที่รัก "พฤติกรรมที่ไม่ได้กำหนด" เมื่อภาษาอื่นล้มเหลว c / c ++ ทำงานในรูปแบบ "undefined" :) แน่นอนว่ามันเป็นส่วนสำคัญของเสน่ห์ของพวกเขา และฉันไม่ได้ล้อเล่น
shylent

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 compiler บน 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

คำเตือนนี้อาจช่วยระบุว่าไฟล์อาจถูกตัดทอนอย่างใด มันเป็นความจริงที่คอมไพเลอร์อาจจะโยนข้อผิดพลาดคอมไพเลอร์ต่อไป - โดยเฉพาะอย่างยิ่งถ้ามันอยู่ตรงกลางของฟังก์ชั่น - หรืออาจเป็นข้อผิดพลาด linker แต่สิ่งเหล่านี้อาจเป็นความลับมากกว่าและไม่รับประกันว่าจะเกิดขึ้น

แน่นอนว่าคำเตือนนี้ยังไม่รับประกันว่าไฟล์จะถูกตัดทอนทันทีหลังจากขึ้นบรรทัดใหม่ แต่ก็อาจยังคงมีบางกรณีที่ข้อผิดพลาดอื่น ๆ อาจพลาดและให้คำแนะนำที่ชัดเจนกับปัญหา


-2

นั่นไม่ใช่ข้อผิดพลาด มันเป็นเพียงคำเตือน

เปิดไฟล์ในตัวแก้ไขไปที่บรรทัดสุดท้ายของไฟล์และกด Enter เพื่อเพิ่มบรรทัดว่างที่ท้ายไฟล์

แต่นอกจากนั้นคุณควรจะใช้แทน#include <iostream> <iostream.h>จากนั้นใส่ในusing std::cout;ภายหลัง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.