我遇到了我不理解的行为。我想要有趣的返回一个 2 字节的值。我创建了一个 4 字节的 var 来进行一些处理并返回变量。我的假设是变量被隐式转换为short。但是,返回值似乎不是 2 字节,因为 printf fun 打印的值大于 2^16,除非我在 fun() 之前放置(短)。这是为什么?
short fun()
{
long var = 2<<20;
return var;
}
printf("%i", fun());
可变参数函数,例如在其操作数上printf
执行所谓的默认参数提升。特别是,小于int
(例如)的整数在传递给可变参数函数时会short
自动变宽。int
解决这个问题的一种方法是使用h
长度修饰符,它说“即使你正在处理一个int
值,假装它真的是一个short
”。然后,printf
将值缩小到short
格式化输出之前。例如:
printf("%hi", fun());
在return var;
中, 的值var
被转换为函数的返回类型,即short
。由于该值超出了short
C 实现的范围,因此存在溢出。C 规范没有定义整数溢出时会发生什么。
尽管如此,这种行为还是有点奇怪。在printf
调用中,许多 C 实现将仅使用 16 位fun()
,将它们提升为int
,并将它们传递给printf
。因此,尽管溢出,输出仍将为“0”。
在您的情况下可能发生的情况是编译器short
通过简单地忽略它并将值保留在保存它的处理器寄存器中来实现转换var
(并使用相同的寄存器返回函数值)。这在 C 标准中是允许的,因为如果long
寄存器中的值在short
域中,那么当解释为 a 时,保持位不变会产生相同的值short
。如果long
值在short
域之外,那么发生什么并不重要,因为 C 标准没有定义必须发生什么。
printf
然后将寄存器的内容简单地作为参数直接传递给。同样,这是有效的,因为如果值在域中,它会产生正确的结果,如果值不在short
域中,则允许任何事情。var
short
你从10
左移 20开始,1000000000000000000000
它超出了 short 的范围,并将它传递给一个获取可变参数的函数(...)
当 printf (和其他可变参数函数)查看该值时,它基本上只是一个内存位置,它使用格式说明符将其转换回原始类型。这是它基本上在做什么的宏观示例:
#define va_arg(ap,type) (*(type *)(((ap)+=(((sizeof(type))+(sizeof(int)-1)) \
& (~(sizeof(int)-1))))-(((sizeof(type))+ \
(sizeof(int)-1)) & (~(sizeof(int)-1)))))
如果您添加了将其转换为 short 的格式说明符,它可以看到转换为 short。除此之外,只需保持(短)-ing 你的乐趣()。