簡體   English   中英

printf / sprintf編譯器警告是否有概念上的突破?

[英]Are printf/sprintf compiler warnings a conceptual break?

我注意到,當printf / sprintf函數的格式字符串中的轉換說明符與相應參數的類型或計數不匹配時,大量C編譯器會發出警告。

在我看來,這似乎是一個概念上的突破,因為根據語言規范,C沒有內置函數。

所有編譯器都應該知道printf / sprintf是他們的原型而不是他們的語義。 我知道printf / sprintf是標准的C函數,但是它們存在於一個單獨的庫libc中,你必須包含stdio.h才能導入它們的原型。

許多編譯器所做的是分析格式字符串,該格式字符串也可以在運行時提供。

以上是否有意義?

“所有編譯器都應該知道printf / sprintf是他們的原型,而不是他們的語義”。

這是不正確的部分。 就標准而言,C實現的任何部分都“被允許”了解任何其他部分,並發布可能對用戶有幫助的診斷。 標准不要求編譯器內在函數,這也不是特定的診斷,但它們當然不是禁止的。

請注意(就標准而言)標准庫是特殊的,它不僅僅是任何舊的鏈接庫。 如果特定的實現/編譯器甚至為用戶提供了一種鏈接不同版本的標准庫的機制,那么當該替代庫具有與其中所列出的語義不同的語義時,該標准當然不要求它“工作”。標准。

所以在這個意義上,標准庫中的所有內容都是“bult-ins”。 它是C語言規范的一部分。 允許編譯器在假設其行為符合標准要求的情況下執行操作。

當然,如果格式說明符在運行時才知道,那么編譯器就無法對varargs進行靜態檢查。 但是當它在編譯時已知時,編譯器可以假設printf的行為與它可以假設memcpy或整數加法的行為一樣有效。

如果我正確地閱讀了你的問題,我同意你的前提,即編譯器對printf和朋友的格式字符串的驗證是一種概念性的活動,與編譯器完成的其他種類的靜態檢查(語法,類型等)不同。

但是,它是標准所允許的,並且可以幫助我們糟糕的程序員。

編譯器的任務只是給你一些有用的提示。 標准不涵蓋此行為。

實施可能會在許多情況下產生警告,其中沒有一個被指定為本國際標准的一部分。

從理論上講,沒有什么能阻止編譯器警告你(可能)錯誤地使用QT庫。

printf是標准功能,因為它(包括其語義)被ISO C標准所涵蓋。

標准在某些情況下需要診斷,但不禁止常規診斷。 任何實現都可以出於任何原因自由發布診斷,包括不正確使用printf()或過度使用字母Q.顯然,其中一些原因比其他原因更有用。

此外,如果包含庫,則其中的所有可見標識符都將保留。 您不能#include <stdio.h>並擁有自己的printf定義(參見C99標准草案的7.1.3)。 這意味着實現可以自由地假設您正在使用標准printf並將其視為標准的必需部分。

這些警告表明可能存在錯誤,因此非常有用。

是的,在編譯器中有警告的特殊情況可能看起來不一致(假設<stdio.h>不僅具有__printf_format_warning屬性或類似的東西),但是如果它有用並且有助於解決一些錯誤(也許甚至安全漏洞),為什么不擁有它們呢?

我的意思是,並不是每個人都只用自己的libc替換他們的libc,具有不同的printf語義......

編程語言標准的最終目的是幫助程序員編寫符合預期的程序。 標准中沒有任何內容表明如果遇到“bigvar = byte3 << 24 + byte2 << 16 + byte1 << 8 + byte0;”,編譯器應該發出警告,但由於結果可能不是程序員打算,許多編譯器會發出警告。 標准對警告施加的唯一限制是它們不能阻止合法程序的成功編譯(例如,在輸出999警告后輸出錯誤的編譯器,或者為了所有實際目的,輸出如此多的警告編譯將會,永遠不會完成,不符合規定)。

沒有任何要求編譯器“知道”標准庫,但也沒有要求如果有人#includes正常的標題,它就不知道它們。 a program includes <stdio.h> I think it would be permissible under the standard for a compiler to replace a printf call that it can understand with something that might be easier to process at run-time (eg it could replace printf("Q%5d",foo); with "putch('Q'); __put_int(foo,5);" if desired). 實際上, 一個程序包含<stdio.h>我認為在編譯器的標准下允許替換一個可以在運行時更容易處理的東西(例如它可以替換printf)的printf調用是允許的(“Q%5d”,foo);“putch('Q'); __put_int(foo,5);”如果需要,“。 如果程序沒有#include <stdio.h>,則禁止此類翻譯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM