使用 printf 的 %s 说明符打印 NULL 的行为是什么? [英] What is the behavior of printing NULL with printf's %s specifier?

查看:39
本文介绍了使用 printf 的 %s 说明符打印 NULL 的行为是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

遇到一个有趣的面试问题:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆