Peringatan kompiler "Tidak ada baris baru di akhir file"

187

Apa alasan untuk peringatan berikut di beberapa kompiler C ++?

Tidak ada baris baru di akhir file

Mengapa saya harus memiliki baris kosong di akhir file sumber / header?

Brian Tompsett - 汤 莱恩
sumber
17
Tidak benar-benar alasannya, tetapi sangat menjengkelkan jika Anda catmemiliki file dan tidak memiliki baris tambahan karena prompt shell baru akan muncul setelah baris terakhir file (yaitu tidak di kolom 0)
ThiefMaster
@ThiefMaster $ PS1 saya dimulai dengan baris baru karena alasan itu. (Bagaimanapun, ini adalah prompt multi baris, yang berisi banyak info berguna pada satu baris dan kemudian hanya karakter prompt di baris berikutnya sehingga perintah yang cukup panjang tidak dapat dibungkus)
bames53
7
Why should I have an empty line at the end of a source/header file- Jika file teks berisi one\ntwo\nthree\nmaka berisi tiga baris, tidak ada yang kosong. Jika file teks berisi one\ntwo\nthreemaka itu bukan file teks, dalam arti yang sama bahwa kalimat tanpa berhenti pada akhirnya bukanlah sebuah kalimat.
Brandin

Jawaban:

217

Pikirkan beberapa masalah yang dapat terjadi jika tidak ada baris baru. Menurut standar ANSI, #includefile di awal memasukkan file persis seperti di depan file dan tidak menyisipkan baris baru setelah #include <foo.h>setelah isi file. Jadi jika Anda memasukkan file tanpa baris baru di akhir parser itu akan dilihat seolah-olah baris terakhir foo.hberada di baris yang sama dengan baris pertama foo.cpp. Bagaimana jika baris terakhir foo.h adalah komentar tanpa baris baru? Sekarang baris pertama foo.cppdikomentari. Ini hanya beberapa contoh dari jenis masalah yang dapat merambah.


Hanya ingin menunjukkan pihak yang tertarik pada jawaban James di bawah ini. Sementara jawaban di atas masih benar untuk C, standar C ++ yang baru (C ++ 11) telah diubah sehingga peringatan ini seharusnya tidak lagi dikeluarkan jika menggunakan C ++ dan kompiler yang sesuai dengan C ++ 11.

Dari standar C ++ 11 melalui pos James:

File sumber yang tidak kosong dan yang tidak diakhiri dengan karakter baris baru, atau yang berakhir dengan karakter baris baru segera didahului oleh karakter backslash sebelum terjadi penyambungan seperti itu, harus diproses seolah-olah ada tambahan baru karakter baris ditambahkan ke file (C ++ 11 §2.2 / 1).

TJ Seabrooks
sumber
28
Tentu saja dalam praktiknya setiap kompiler menambahkan baris baru setelah #include. Untungnya
mxcl
3
Saya ingat versi lama dari Microsoft Visual C ++ (seperti 2.x atau sesuatu) memiliki masalah ini. Itu diperparah karena editor IDE mendorong semacam perilaku baris baru yang hilang ini.
Greg Hewgill
2
Compiler mungkin tidak mengeluh saat ini, tetapi GitHub sebenarnya mengompol.
Puyover
1
Saya bisa melihat "di bawah" oleh James tetapi: "Jawaban di atas" di OrderBy what ?! Di atas adalah pertanyaan, karena saya biasanya memesan dengan suara. Atau maksud Anda jawaban Anda sendiri?
mbx
@Thomas: Apakah program ini memanggil perilaku yang tidak terdefinisi karena tidak berakhir dengan baris baru. Lihat program di sini: ideone.com/jswwf9
Destructor
44

Persyaratan bahwa setiap file sumber berakhir dengan baris baru yang tidak terhapus telah dihapus dalam C ++ 11. Spesifikasi sekarang berbunyi:

File sumber yang tidak kosong dan yang tidak diakhiri dengan karakter baris baru, atau yang berakhir dengan karakter baris baru segera didahului oleh karakter backslash sebelum terjadi penyambungan seperti itu, harus diproses seolah-olah ada tambahan baru karakter baris ditambahkan ke file (C ++ 11 §2.2 / 1).

Compiler yang menyesuaikan seharusnya tidak lagi mengeluarkan peringatan ini (setidaknya tidak ketika mengkompilasi dalam mode C ++ 11, jika kompiler memiliki mode untuk revisi yang berbeda dari spesifikasi bahasa).

James McNellis
sumber
4
Itu semua baik dan bagus untuk C ++; Sayangnya, C masih mengatakan itu UB, bahkan dalam konsep terbaru standar C1X mendatang.
Adam Rosenfield
11
Pertanyaan ini ditandai [c ++] dan bukan [c].
James McNellis
3
Meski begitu, mungkin harus ditandai [c], karena banyak orang yang mencari peringatan ini di C akan menemukan jalan mereka di sini.
Adam Rosenfield
1
Ini masih bagus untuk ditambahkan. Menambahkan ini di atas. Semoga kamu tidak keberatan.
TJ Seabrooks
25

C ++ 03 Standard [2.1.1.2] menyatakan:

... Jika file sumber yang tidak kosong tidak berakhir pada karakter baris baru, atau berakhir pada karakter baris baru segera didahului oleh karakter backslash sebelum terjadi penyambungan, perilaku tersebut tidak ditentukan.

Igor Semenov
sumber
16

Jawaban untuk "patuh" adalah "karena Standar C ++ 03 mengatakan perilaku suatu program yang tidak berakhir pada baris baru tidak ditentukan" (diparafrasekan).

Jawaban bagi yang penasaran ada di sini: http://gcc.gnu.org/ml/gcc/2001-07/msg01120.html .

Vytautas Shaltenis
sumber
4
Ahh, "perilaku tak terdefinisi" tercinta. Ketika bahasa lain gagal, c / c ++ berperilaku dengan cara "tidak terdefinisi" :) Itu, tentu saja, adalah bagian besar dari pesona mereka. Dan aku tidak bercanda.
shylent
6

Itu tidak merujuk ke baris kosong, itu adalah apakah baris terakhir (yang dapat memiliki konten di dalamnya) diakhiri dengan baris baru.

Sebagian besar editor teks akan meletakkan baris baru di akhir baris terakhir file, jadi jika baris terakhir tidak memilikinya, ada risiko file tersebut telah terpotong. Namun, ada alasan yang sah mengapa Anda mungkin tidak ingin baris baru jadi itu hanya peringatan, bukan kesalahan.

Leigh Caldwell
sumber
5

#includeakan mengganti barisnya dengan konten literal dari file tersebut. Jika file tidak diakhiri dengan baris baru, baris berisi #includeyang menariknya akan bergabung dengan baris berikutnya.

bayangan bulan
sumber
2

Saya menggunakan c-free IDE versi 5.0, dalam program saya baik bahasa 'c ++' atau 'c' saya mendapatkan masalah yang sama. Tepat di akhir program, yaitu baris terakhir dari program (setelah penyangga fungsi, mungkin utama atau fungsi apa saja), tekan enter- line no. akan bertambah 1. kemudian jalankan program yang sama, itu akan berjalan tanpa kesalahan.

divesh
sumber
2

Tentu saja dalam praktiknya setiap kompiler menambahkan baris baru setelah #include. Untungnya - @mxcl

bukan C / C ++ spesifik tetapi dialek C: saat menggunakan GL_ARB_shading_language_includeekstensi, kompiler glsl di OS X memperingatkan Anda BUKAN tentang baris baru yang hilang. Jadi Anda dapat menulis MyHeader.hfile dengan pelindung kepala yang berakhir dengan #endif // __MY_HEADER_H__dan Anda akan kehilangan garis setelah #include "MyHeader.h"yakin.

Jan-Philip Loos
sumber
2

Karena perilaku berbeda antara versi C / C ++ jika file tidak berakhir dengan baris baru. Terutama jahat adalah versi C ++ - yang lebih lama, fx dalam C ++ 03 kata standar (fase terjemahan):

Jika file sumber yang tidak kosong tidak diakhiri dengan karakter baris baru, atau diakhiri dengan karakter baris baru segera didahului oleh karakter backslash, perilaku tidak terdefinisi.

Perilaku tidak terdefinisi buruk: kompiler penyesuai standar dapat melakukan lebih atau kurang apa yang diinginkannya di sini (masukkan kode jahat atau apa pun) - jelas alasan peringatan.

Meskipun situasinya lebih baik di C ++ 11, adalah ide yang baik untuk menghindari situasi di mana perilaku tidak terdefinisi dalam versi sebelumnya. Spesifikasi C ++ 03 lebih buruk daripada C99 yang langsung melarang file tersebut (perilaku kemudian didefinisikan).

meroket
sumber
Saya menduga Standar mengatakan bahwa program-program tanpa baris baru yang tertinggal memiliki Perilaku Tidak Terdefinisi, daripada menyatakan bahwa mereka tidak terbentuk dengan baik, karena beberapa kompiler akan menggabungkan baris akhir yang tidak diakhiri dari file yang disertakan dengan teks kode sumber mengikuti #includearahan , dan beberapa programmer yang menargetkan kompiler semacam itu mungkin telah mengeksploitasi perilaku tersebut. Memiliki Standar meninggalkan hal-hal seperti itu Undefined akan memungkinkan program mengeksploitasi keanehan seperti itu didefinisikan dengan baik pada platform yang menentukan perilaku tersebut. Memiliki Standar mandat perilaku akan merusak program tersebut.
supercat
0

Peringatan ini mungkin juga membantu untuk menunjukkan bahwa suatu file bisa saja terpotong. Memang benar bahwa kompiler mungkin akan melemparkan kesalahan kompiler - terutama jika itu di tengah fungsi - atau mungkin kesalahan linker, tetapi ini bisa lebih samar, dan tidak dijamin akan terjadi.

Tentu saja peringatan ini juga tidak dijamin jika file terpotong segera setelah baris baru, tetapi masih bisa menangkap beberapa kasus bahwa kesalahan lain mungkin terlewatkan, dan memberikan petunjuk yang lebih kuat untuk masalah ini.

mwfearnley
sumber
-2

Itu bukan kesalahan. Itu hanya peringatan.

Buka file dalam editor, pergi ke baris terakhir file, dan tekan enter untuk menambahkan baris kosong ke akhir file.

Padahal, selain itu, Anda harus menggunakan #include <iostream>bukan <iostream.h>. Lalu masukkan using std::cout;setelah itu.

keya
sumber