我写了这个故意错误的代码
printf("%d %d", 1);
用g++
和编译-Werror=format
.
编译器给出了令人印象深刻的警告:
error: format '%d' expects a matching 'int' argument [-Werror=format]
据我所知,编译器无法判断代码是错误的,因为格式字符串直到运行时才被解析.
我的问题:编译器是否有一个特殊的功能,可以用于printf和类似的libc函数,或者这是一个我可以用于自己的函数的功能?字符串文字?
据我所知,编译器无法判断代码是错误的,因为格式字符串直到运行时才被解析.
只要格式字符串是字符串文字,就可以在编译时解析它.如果不是(无论如何通常都是个坏主意),那么你可以从中得到警告-Wformat-security
.
编译器是否有一个特殊的功能,可以启动printf和类似的libc函数?
是.
或者这是我可以用于我自己的功能的功能?
是的,只要你使用的格式字符串作为相同的样式printf
(或其他各种标准功能,如scanf
或strftime
).
void my_printf(Something, char const * format, SomethingElse, ...) __attribute__ ((format (printf,2,4)));
表示第二个参数是一个printf
样式格式字符串,格式值以第四个开头.请参阅http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html.
好吧,printf
绝对要在运行时解析格式字符串才能完成它的工作.但是,如果它想要,编译器可能不会选择自己解析它.
文档-Wformat
说明这正是发生的事情:
-Wformat
-Wformat=n
检查电话
printf
和scanf
等,以确保提供参数>适当指定的格式字符串类型,并在格式字符串指定的转换是有意义的.这包括标准的功能,以及其他由格式属性指定(见函数属性),在printf
,scanf
,strftime
和strfmon
(一个X /开启延伸,而不是在C标准)的家庭(或其他靶特异性家庭).在没有指定格式属性的情况下检查哪些函数取决于所选的标准版本,并且对没有指定属性的函数的这种检查由-ffreestanding
或禁用-fno-builtin
.根据GNU libc 2.2版支持的格式功能检查格式.这些包括所有ISO C90和C99功能,以及单Unix规范和一些BSD和GNU扩展的功能.其他库实现可能不支持所有这些功能; GCC不支持警告超出特定库限制的功能.但是,如果-Wpedantic与-Wformat一起使用,则会给出关于不在所选标准版本中的格式功能的警告(但不是针对strfmon格式的警告,因为这些格式不在C标准的任何版本中).请参阅选项控制C方言.
更新:原来你可以在你自己的功能上使用它.迈克有详细信息.