这会调用未定义的行为吗?
考虑以下 C 程序:
#include <stdio.h>
int main(){
int a =-1;
unsigned b=-1;
if(a==b)
printf("%d %d",a,b);
else
printf("Unequal");
return 0;
}
在 printf("%d %d",a,b);
行中,"%d"
用于打印无符号类型。这是否会引发未定义的行为,为什么?
Consider the following C program:
#include <stdio.h>
int main(){
int a =-1;
unsigned b=-1;
if(a==b)
printf("%d %d",a,b);
else
printf("Unequal");
return 0;
}
In the line printf("%d %d",a,b);
, "%d"
is used to print an unsigned type. Does this invoke undefined behavior and why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
尽管明确允许您使用
中的va_arg
宏来检索作为unsigned
传递的参数int
(7.15.1.1/2),在fprintf
(7.19.6.1/9) 的文档中,它也适用于printf
,它明确声明如果任何参数不是格式说明符的正确类型(对于未修改的%d
,即int
),则未定义行为。正如 @bdonlan 在评论中指出的那样,如果
b
的值(在本例中,对于某些N
为2^N - 1
)是不可表示的在int
中,那么尝试在任何int
中使用va_arg
访问该值将是未定义行为案件。这只适用于无符号表示至少使用一个填充位的平台,而相应的 int 表示具有符号位。即使在
(unsigned)-1
的值可以用int
表示的情况下,我仍然认为这在技术上是未定义的行为 。作为实现的一部分,似乎允许实现使用内置魔法而不是va_args
来访问printf
的参数,并且如果您将某些内容作为如果需要int
,那么您在技术上就违反了printf
的约定。Although you are explicitly allowed to use the
va_arg
macro from<stdarg.h>
to retrieve a parameter that was passed as anunsigned
as anint
(7.15.1.1/2), in the documentation forfprintf
(7.19.6.1/9) which also applies toprintf
, it explicitly states that if any argument is not the correct type for the format specifier - for an unmodified%d
, that isint
- then the behaviour is not defined.As @bdonlan notes in a comment, if the value of
b
(in this case2^N - 1
for someN
) is not representable in anint
then it would be undefined behavior to attempt to access the value as anint
usingva_arg
in any case. This would only work on platforms where the representation of anunsigned
used at least one padding bit where the correspondingint
representation had a sign bit.Even in the case where the value of
(unsigned)-1
can be represented in anint
, I still read this as being technically undefined behavior. As part of the implementation, it would seem to be allowed for an implementation to use built in magic instead ofva_args
to access the parameters toprintf
and if you pass something as anunsigned
where anint
is required then you have technically violated the contract forprintf
.标准在这一点上并不是 100% 明确。一方面,您可以获得
va_arg
的规范,其中表示 (§7.15.1.1/2):另一方面,您可以获得
printf
的规范(§7.19.6.1/9):鉴于
printf
几乎可以肯定将使用va_arg
检索参数,我会说您对于可以在目标类型中表示的值非常安全,但由于您在传递之前已将 -1 转换为无符号,因此该值将超出可以表示的范围。在一个有符号的 int 中,所以行为将是 不明确的。The standard isn't 100% clear on this point. On one hand, you get the specification for
va_arg
, which says (§7.15.1.1/2):On the other hand, you get the specification of
printf
(§7.19.6.1/9):Given that it's pretty much a given that
printf
will retrieve arguments withva_arg
, I'd say you're pretty safe with values that can be represented in the target type, but not otherwise. Since you've converted -1 to an unsigned before you pass it, the value will be out of the range that can be represented in a signed int, so the behavior will be undefined.是的,
if
将始终评估为 true,而printf
将尝试将unsigned
打印为signed
。由于signed
类型可能具有陷阱表示,如果符号表示是补码,则这可能是UB。Yes, the
if
will always evaluate to true and theprintf
will attempt to print anunsigned
as asigned
. Since thesigned
type may have trap representations, this may be UB if the sign representation is one's complement.