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

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

问题描述

跨越有趣的采访问题就来了

 测试1:
的printf(测试%S \\ n,NULL);
的printf(测试%S \\ n,NULL);打印:
测试(空)
测试(空)测试2:
的printf(%S \\ n,NULL);
的printf(%S \\ n,NULL);
版画
分段错误(核心转储)

虽然这样可能在某些系统上运行良好,ATLEAST矿是扔分割故障。
什么是这种行为的最好解释?上述code是在C

以下是我的gcc信息:

 深@深:〜$ GCC --version
海湾合作委员会(Ubuntu的/ Linaro的4.6.3-1ubuntu5)4.6.3


解决方案

首先:的printf 期待一个有效的(即非NULL)
指针的%S参数,所以它传递一个NULL正式
未定义。它可以打印(空),或者它可能会删除所有文件的
硬盘驱动器 - 无论是正确的行为尽可能ANSI关注
(至少,这就是哈比森和斯蒂尔告诉我。)

话虽这么说,是啊,这真是奇怪的行为。原来,
那是什么发生的事情是,当你做一个简单的的printf 是这样的:

 的printf(%S \\ n,NULL);

GCC是(啊哈的),足够聪明,解构到以式电话本
看跌。第一个的printf ,这样的:

 的printf(测试%S \\ n,NULL);

足够复杂,GCC反而会散发出真实的呼叫
的printf

(请注意,海湾合作委员会发出有关无效的printf 参数警告
当你编译。这是因为它早就开发的能力,
解析 *的printf 格式字符串。)

您可以通过使用 -save-临时工编制看到自己选项
然后通过产生的 .S 文件中查找。

当我编译第一个例子中,我得到了:

  MOVL $ .LC0,EAX%
MOVL $ 0%ESI
MOVQ%RAX,%RDI
MOVL $ 0,%EAX
调用printf; < - 其实调用printf!

(评论是由我所加)

但第二个生成此code:

  MOVL $ 0%EDI;商店在看跌期权参数列表NULL
调用看跌期权;呼叫看跌期权

的奇怪的事情是,它不打印以下换行符。
就好像它是想通了,这是要引起段错误
所以它不打扰。 (它有 - 它提醒我,当我编译
它)。

Came across an interesting interview question:

test 1:
printf("test %s\n", NULL);
printf("test %s\n", NULL);

prints:
test (null)
test (null)

test 2:
printf("%s\n", NULL);
printf("%s\n", NULL);
prints
Segmentation fault (core dumped)

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.

Following is my gcc info:

deep@deep:~$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

解决方案

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.)

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\n", NULL);

gcc is (ahem) smart enough to deconstruct this into a call to puts. The first printf, this:

printf("test %s\n", NULL);

is complicated enough that gcc will instead emit a call to real 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.)

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!

(Comments were added by me.)

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.)

这篇关于什么是NULL印刷用的printf的%S说明的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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