有人可以解释为什么运行以下代码只打印换行符吗?
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
int x = 12;
char *s = (char *) &x;
printf("%s\n", s);
return 0;
}
由于我们将&x
转换为字符串,因此打印的内容不应该是x
地址的字符串表示形式(可能是某个十六进制内存地址)?
答案 0 :(得分:6)
您的代码展示undefined behavior,因为您尝试使用%s
打印int的地址。
%s
函数族中的 printf
用于打印\0
终止的字符数组或c-type strings
根据C11规范, 7.21.6.1 fprintf函数
(8)%s:如果不存在l长度修饰符,则参数应为指向 字符类型数组的初始元素。 280)来自的字符 数组被写入(但不包括)终止空值 字符。如果指定了精度,则不超过那么多字节 写的。如果未指定精度或大于 数组的大小,数组应包含一个空字符。
280)对多字节字符没有特殊规定
以后
(9)如果转换规范无效,则行为为 undefined。 282)如果任何参数不是正确的类型 相应的转换规范,行为未定义。
282)参见“未来的图书馆方向”(7.31.11)。
可能发生的许多可能性之一是:(我在这里假设很多关于实施的内容)
你的int出现在内存中,跟随4个字节
s (not guaranteed to hold the same address)
s s+1 s+2 s+3 s+4
+---+---+---+---+
| 0 | 0 | 0 | 12|
+---+---+---+---+
&x
或
s (not guaranteed to hold the same address)
s s+1 s+2 s+3 s+4
+---+---+---+---+
| 12| 0 | 0 | 0 |
+---+---+---+---+
&x
其中12或换页或\f
是不可打印的ascii字符,可能无法在屏幕上打印任何内容。
当您将其重新解释为char *
并打印时,将打印一个空字符串,然后打印换行符。虽然这不能得到保证,但任何事情都可能从崩溃到无限期(甚至更糟)的打印中发生。
打印int
的正确方法是:
printf("%d\n", x);
答案 1 :(得分:6)
字符串是一系列字符,以特殊字符map_versions tags
结尾。使用'\0'
格式打印字符串时,"%s"
函数将地址作为基址,并从该基数打印字符,直到找到终结符。如果“string”实际上不是字符串,则为undefined behavior。
如果您要打印地址,请使用printf
格式:
"%p"