2017-07-18 75 views
-1
#include<stdio.h> 
void main() 
{ 
    int n = 2; 
    printf("%c",&n); 
} 

输出:L试图了解printf的一个指针有一个char说明符(%C)

在使用%d它当然给出可变n的地址,但它为什么使用%c输出L&

+5

因为指针不是字符,所以这段代码是**未定义的行为**。它也可以做其他任何事情。这是对你的特定环境的一种随机效应,当printf()的一个指针的一部分在尝试获得一个字符转换为H时将会评估它... –

+2

我可以闻到UB。唯一发生的事情是UB。 –

+2

呵呵,所以**现在**它*突然*“L”?你觉得现在有什么不完美吗? –

回答

-1

这是因为您告诉printf()函数将int n的地址的前1个字节显示为char。

8

它是未定义的行为因为您已经使用了错误的格式说明符

C11标准:7.21.6.1:第9段:

如果转换规格是无效,该行为是 未定义。如果任何参数不是相应转换规范的正确类型,则行为是undefined

这意味着如果使用错误的格式说明符调用printf会发生任何事情。

4

由于rsp的其他answer表示行为未定义,任何事情都可能发生。

在你的情况会发生以下情况:

它读取的&n一个字节,因为一个字符是一个字节大小其中大部分是8位长的,看到CHAR_BIT explanation on SO。然后它将它打印为字符。
如果您的机器上的int*int类型相同,则该字节可能是&n的第一个字节。这意味着您的变量n位于地址0x48...(big-endian)或0x...48(little-endian),因为0x48HAscci code。我假设你的程序正在使用Ascii进行编码,但这不一定非要。
(您改变了角色从HL但我离开这个答案,因为它是。)
此外该字节可以在&n中间的某处如果int*超过你的系统的int的大小。

你应该在GCC例如-Wall使更多的警告编译,您将获得:

警告:格式“%C”需要类型“诠释”的说法,但参数2的类型为“廉政* '[-Wformat =]

在这种情况下你施放该值到char的行为将被明确限定,但是依赖于实现作为指针类型的铸造为整数被定义实现。

尽管如此,你在做什么也没有意义,它不会做的演员。

+1

还有一些不精确的地方(这很容易引发UB):1.)ascii没有强制要求2.)char'总是**一个字节,但一个字节可能有多于8位3)使用转换,它不是未定义的,但仍然不是特别有用,因为指针转换为整数类型的结果是*实现定义的* - 仍然是upvoted,解释是有帮助的! –

+0

@FelixPalmen:谢谢你的解释! –

+0

答案假设'int'和'int *'是相同的大小,并且'int'和'int *'通过相同的机制传递给'printf()'。在C. – chux