这会调用未定义的行为吗?

发布于 2024-11-04 06:35:05 字数 302 浏览 1 评论 0原文

考虑以下 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

悍妇囚夫 2024-11-11 06:35:05

尽管明确允许您使用 中的 va_arg 宏来检索作为 unsigned 传递的参数int (7.15.1.1/2),在 fprintf (7.19.6.1/9) 的文档中,它也适用于 printf,它明确声明如果任何参数不是格式说明符的正确类型(对于未修改的 %d,即 int),则未定义行为。

正如 @bdonlan 在评论中指出的那样,如果 b 的值(在本例中,对于某些 N2^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 an unsigned as an int (7.15.1.1/2), in the documentation for fprintf (7.19.6.1/9) which also applies to printf, it explicitly states that if any argument is not the correct type for the format specifier - for an unmodified %d, that is int - then the behaviour is not defined.

As @bdonlan notes in a comment, if the value of b (in this case 2^N - 1 for some N) is not representable in an int then it would be undefined behavior to attempt to access the value as an int using va_arg in any case. This would only work on platforms where the representation of an unsigned used at least one padding bit where the corresponding int representation had a sign bit.

Even in the case where the value of (unsigned)-1 can be represented in an int, 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 of va_args to access the parameters to printf and if you pass something as an unsigned where an int is required then you have technically violated the contract for printf.

酒绊 2024-11-11 06:35:05

标准在这一点上并不是 100% 明确。一方面,您可以获得 va_arg 的规范,其中表示 (§7.15.1.1/2):

如果没有实际的下一个参数,或者如果
类型与实际下一个参数的类型不兼容(根据
到默认参数促销),行为未定义,但以下情况除外
案例:

  • 一种类型是有符号整数类型,另一种类型是相应的无符号整数
    类型,并且该值可以用两种类型表示;
  • 一种类型是指向 void 的指针,另一种类型是指向字符类型的指针。

另一方面,您可以获得 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):

If there is no actual next argument, or if
type is not compatible with the type of the actual next argument (as promoted according
to the default argument promotions), the behavior is undefined, except for the following
cases:

  • one type is a signed integer type, the other type is the corresponding unsigned integer
    type, and the value is representable in both types;
  • one type is pointer to void and the other is a pointer to a character type.

On the other hand, you get the specification of printf (§7.19.6.1/9):

If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined."

Given that it's pretty much a given that printf will retrieve arguments with va_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.

清醇 2024-11-11 06:35:05

是的,if 将始终评估为 true,而 printf 将尝试将 unsigned 打印为 signed。由于signed类型可能具有陷阱表示,如果符号表示是补码,则这可能是UB。

Yes, the if will always evaluate to true and the printf will attempt to print an unsigned as a signed. Since the signed type may have trap representations, this may be UB if the sign representation is one's complement.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文