困惑为什么功能不打印地址

时间:2015-05-26 07:27:37

标签: c printf

有人可以解释为什么运行以下代码只打印换行符吗?

#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地址的字符串表示形式(可能是某个十六进制内存地址)?

2 个答案:

答案 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"