October 28, 2007

警告:"no newline at end of file"

拜讀 [一個細節引發的思考] 一文有感,遂作此筆記。許多人花了耗費上萬元學習 C 語言程式設計,卻吝惜花點錢買份 C language specification,這是多麼可惜的事?我們不時可從許多細節學習到這一系列標準背後的真義與價值,比方說今天要探討的常見 GNU C compilation warning:
    warning: no newline at end of file
這種編譯時期警告很容易重現 (reproduce),只要餵給 gcc 一個非空白的檔案即可,如以下操作:
    $ echo -n "\t" | gcc -E -
    # 1 "<stdin>"
    # 1 "<built-in>"
    # 1 "<command line>"
    # 1 "<stdin>"
    <stdin>:1:3: warning: no newline at end of file
    
以上在 echo 指令後加上 "-n" 表示不印出尾端的 newline (CRLF 一類的字元),僅輸出 '\t' (tab 字元),這種警告特別容易發生於專案程式碼切換於 Win32 與 UNIX 系統中編譯,先來「捨近求遠」看看警告是從哪來的?在 gcc-4.1.2 的原始程式碼 libcpp/lex.c 中 _cpp_get_fresh_line 函式有以下實做碼:
/* End of buffer.  Non-empty files should end in a newline.  */
if (buffer->buf != buffer->rlimit
    && buffer->next_line > buffer->rlimit
    && !buffer->from_stage3)
  {
    /* Only warn once.  */

    buffer->next_line = buffer->rlimit;
    cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line_table->highest_line,
                         CPP_BUF_COLUMN (buffer, buffer->cur),
                         "no newline at end of file");
  }
註解文字引人深思 "Non-empty files should end in a newline.",於是我們來查閱同樣在 gcc 原始程式碼內建的文件 doc/implement-c.texi,提到:
    Whether each nonempty sequence of white-space characters other than new-line is retained or replaced by one space character in translation phase 3 (C90 and C99 5.1.1.2).
在 GCC 4 系列中,貫徹完整的 C99 (由 ISO 與 IEC 於 1999 年制定的 C programming language standard ISO/IEC 9899) 是重要的目標,特別在未來的 gcc 4.3 (mainline) 系列中,抑制許多不符規格的語法。我們可從 [ISO C Working Group] (WG14) 的文件 [Rationale for the C99 standard] (PDF) 得知 C99 章節 5.1.1.2 相關的訊息:
    A backslash immediately before a newline has long been used to continue string literals, as well as preprocessing command lines. In the interest of easing machine generation of C, and of transporting code to machines with restrictive physical line lengths, the C89 Committee generalized this mechanism to permit any token to be continued by interposing a backslash/newline sequence.
由此可見,為了一致性,原始程式碼每一行後「應該要」有一個象徵結束的字元,也就是 newline,在不同的軟硬體平台有對應的表示,如 CRLF (Win32) 或 CR/LF (UNIX/MacOS)。原本是很單純的細節,倘若我們一味不思索規格本身的意義,僅是得過且過、淺嘗輒止,怎能獲得成長呢?
由 jserv 發表於 October 28, 2007 02:57 PM
迴響

那為何 SPEC 要做這種規範? 我覺得這比較有意義。
幾年前忘了在哪邊看到的,說是避免當被 include 的檔案展開後,兩個檔案中前一個檔案的最後一行與後一個檔案的第一行直接被接成一行所造成的錯誤.
不過後來大部分的 compiler 應該都會幫你插了斷行符號,並且吐個 warning 出來。

av 發表於 October 28, 2007 11:10 PM

惡搞中文 Python 的時候,
就發現 gasolin 在 MAC 下出來的代碼在 svn diff 經常
報 no newline at end of file
\ 文件結尾缺少空行

華華 發表於 October 28, 2007 11:51 PM

我的英文不大好... 不過 jserv 引用的那段英文(C99 章節 5.1.1.2 相關的訊息)好像已經把 av 先生說的那的意義包進來了。

anton 發表於 October 29, 2007 11:08 AM

20 transporting code to machines with restrictive physical line lengths 是代表什麼意思呢 ?

Mai 發表於 November 1, 2007 01:26 AM

To Mai,

"20" 是誤植的文件行號,已修正,謝謝!
該行是 C 標準會議的委員對 C 語言編譯器實做所做出的考量,認為需要有明確的輸入規範,如前述所及的行尾識別字元。

jserv 發表於 November 1, 2007 02:02 AM
發表迴響









記住我的資訊?