使用 printf 的 %s 说明符打印 NULL 的行为是什么? [英] What is the behavior of printing NULL with printf's %s specifier?
问题描述
遇到一个有趣的面试问题:
Came across an interesting interview question:
test 1:
printf("test %s
", NULL);
printf("test %s
", NULL);
prints:
test (null)
test (null)
test 2:
printf("%s
", NULL);
printf("%s
", NULL);
prints
Segmentation fault (core dumped)
虽然这可能在某些系统上运行良好,但至少我的会引发分段错误.这种行为的最佳解释是什么?上面的代码是用 C 编写的.
Though this might run fine on some systems, atleast mine is throwing a segmentation fault. What would be the best explanation of this behavior? Above code is in C.
以下是我的 gcc 信息:
Following is my gcc info:
deep@deep:~$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
推荐答案
第一件事:printf
期待一个有效的(即非 NULL)指向其 %s 参数的指针,因此正式将 NULL 传递给它不明确的.它可能会打印(空)"或者可能会删除您的所有文件硬盘驱动器——就 ANSI 而言,这两种行为都是正确的(至少,Harbison 和 Steele 是这么告诉我的.)
First things first: printf
is expecting a valid (i.e. non-NULL)
pointer for its %s argument so passing it a NULL is officially
undefined. It may print "(null)" or it may delete all files on your
hard drive--either is correct behavior as far as ANSI is concerned
(at least, that's what Harbison and Steele tells me.)
话虽如此,是的,这确实是一种奇怪的行为.事实证明发生的事情是,当你像这样做一个简单的 printf
时:
That being said, yeah, this is really wierd behavior. It turns out
that what's happening is that when you do a simple printf
like this:
printf("%s
", NULL);
gcc (ahem) 足够聪明,可以将其解构为调用放置
.第一个printf
,这个:
gcc is (ahem) smart enough to deconstruct this into a call to
puts
. The first printf
, this:
printf("test %s
", NULL);
足够复杂以至于 gcc 将调用 realprintf
.
is complicated enough that gcc will instead emit a call to real
printf
.
(请注意 gcc 会发出有关您无效的 printf
参数的警告当你编译.那是因为它很久以前就发展出这样的能力解析 *printf
格式字符串.)
(Notice that gcc emits warnings about your invalid printf
argument
when you compile. That's because it long ago developed the ability to
parse *printf
format strings.)
您可以通过使用 -save-temps
选项进行编译来自己查看然后查看生成的 .s
文件.
You can see this yourself by compiling with the -save-temps
option
and then looking through the resulting .s
file.
当我编译第一个例子时,我得到:
When I compiled the first example, I got:
movl $.LC0, %eax
movl $0, %esi
movq %rax, %rdi
movl $0, %eax
call printf ; <-- Actually calls printf!
(评论是我加的.)
但是第二个产生了这个代码:
But the second one produced this code:
movl $0, %edi ; Stores NULL in the puts argument list
call puts ; Calls puts
奇怪的是它不打印以下换行符.好像发现这会导致段错误所以它不打扰.(它有 - 它在我编译时警告我它.)
The wierd thing is that it doesn't print the following newline. It's as though it's figured out that this is going to cause a segfault so it doesn't bother. (Which it has--it warned me when I compiled it.)
这篇关于使用 printf 的 %s 说明符打印 NULL 的行为是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!