我遇到了一个我不明白的行为。 我希望有趣的是返回2字节的val。 我创建一个4字节的var来做一些处理并返回变量。 我的假设是变量被隐式转换为short。 但是,似乎返回的值不是2字节,因为printf fun打印的值大于2 ^ 16,除非我在fun()之前放置(short)。 那是为什么?
short fun()
{
long var = 2<<20;
return var;
}
printf("%i", fun());
答案 0 :(得分:3)
printf
等变量函数在其操作数上执行所谓的默认参数提升。特别是,比int
更窄的整数(例如short
)在传递到可变函数时会自动扩展到int
。
解决此问题的一种方法是使用h
长度修饰符,即“即使您正在处理int
值,也假设它实际上是short
”。然后,printf
会在格式化输出之前将值缩小回short
。例如:
printf("%hi", fun());
答案 1 :(得分:1)
从10
开始,左移20到1000000000000000000000
超出短路范围并将其传递给获得可变参数的函数(...)
当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。除此之外,保持(简短) - 你的乐趣()。
答案 2 :(得分:1)
在return var;
中,var
的值将转换为函数的返回类型,即short
。由于该值超出了C实现中short
的范围,因此存在溢出。 C规范没有定义当存在整数溢出时会发生什么。
尽管如此,这种行为有点奇怪。在printf
调用中,许多C实现仅使用fun()
中的16位,将它们提升为int
,并将它们传递给printf
。因此,尽管有溢出,输出仍为“0”。
在您的情况下可能发生的情况是,编译器通过简单地忽略它并将值保留在处理器寄存器中,将值转换为short
(并使用相同的值)来实现转换为var
注册以返回函数值)。 C标准允许这样做,因为如果寄存器中的long
值在short
域中,则在解释为short
时,保持位不变会产生相同的值。如果long
值超出short
域,则无论发生什么都没关系,因为C标准没有定义必须发生的事情。
然后,寄存器的内容直接传递给printf
作为参数。同样,这是有效的,因为如果值在short
域中,它会产生正确的结果,如果var
值不在short
域中,则允许任何内容。