#include<stdio.h>
void main()
{
int n = 2;
printf("%c",&n);
}
输出:L试图了解printf的一个指针有一个char说明符(%C)
在使用%d
它当然给出可变n
的地址,但它为什么使用%c
输出L&
#include<stdio.h>
void main()
{
int n = 2;
printf("%c",&n);
}
输出:L试图了解printf的一个指针有一个char说明符(%C)
在使用%d
它当然给出可变n
的地址,但它为什么使用%c
输出L&
这是因为您告诉printf()函数将int n的地址的前1个字节显示为char。
它是未定义的行为因为您已经使用了错误的格式说明符。
C11标准:7.21.6.1:第9段:
如果转换规格是无效,该行为是 未定义。如果任何参数不是相应转换规范的正确类型,则行为是undefined。
这意味着如果使用错误的格式说明符调用printf
会发生任何事情。
由于rsp的其他answer表示行为未定义,任何事情都可能发生。
在你的情况会发生以下情况:
它读取的&n
一个字节,因为一个字符是一个字节大小其中大部分是8位长的,看到CHAR_BIT
explanation on SO。然后它将它打印为字符。
如果您的机器上的int*
和int
类型相同,则该字节可能是&n
的第一个字节。这意味着您的变量n
位于地址0x48...
(big-endian)或0x...48
(little-endian),因为0x48
是H
的Ascci code。我假设你的程序正在使用Ascii进行编码,但这不一定非要。
(您改变了角色从H
到L
但我离开这个答案,因为它是。)
此外该字节可以在&n
中间的某处如果int*
超过你的系统的int
的大小。
你应该在GCC例如-Wall
使更多的警告编译,您将获得:
警告:格式“%C”需要类型“诠释”的说法,但参数2的类型为“廉政* '[-Wformat =]
在这种情况下你施放该值到char
的行为将被明确限定,但是依赖于实现作为指针类型的铸造为整数被定义实现。
尽管如此,你在做什么也没有意义,它不会做的演员。
还有一些不精确的地方(这很容易引发UB):1.)ascii没有强制要求2.)char'总是**一个字节,但一个字节可能有多于8位3)使用转换,它不是未定义的,但仍然不是特别有用,因为指针转换为整数类型的结果是*实现定义的* - 仍然是upvoted,解释是有帮助的! –
@FelixPalmen:谢谢你的解释! –
答案假设'int'和'int *'是相同的大小,并且'int'和'int *'通过相同的机制传递给'printf()'。在C. – chux
因为指针不是字符,所以这段代码是**未定义的行为**。它也可以做其他任何事情。这是对你的特定环境的一种随机效应,当printf()的一个指针的一部分在尝试获得一个字符转换为H时将会评估它... –
我可以闻到UB。唯一发生的事情是UB。 –
呵呵,所以**现在**它*突然*“L”?你觉得现在有什么不完美吗? –