c - 在 printf 需要 int 的地方给 printf 一个 char 参数是 UB 吗?

标签 c language-lawyer undefined-behavior integer-promotion

我是否正确理解该程序导致UB的标准:

#include <stdio.h>

int main(void)
{
    char a = 'A';
    printf("%c\n", a);
    return 0;
}

当它在 sizeof(int)==1 && CHAR_MIN==0 的系统上执行时?

因为如果 a 是无符号的并且具有与 int 相同的大小 (1),它将被提升为 unsigned int [ 1] (2),而不是 int,因为 int 不能表示 char 的所有值。格式说明符 "%c" 需要一个 int [2],并且在 printf() 中使用错误的符号会导致 UB [3]。

C99 ISO/IEC 9899 的相关引用

[1] 根据 C99 6.3.1.1:2 升级为 int:

If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.

[2] 格式说明符 "%c" 需要一个 int 参数,C99 7.19.6.1:8 c:

If no l length modifier is present, the int argument is converted to an unsigned char, and the resulting character is written.

[3] 在 fprintf() (3) 中使用错误的类型,包括错误的符号,会导致根据 C99 7.19.6.1:9 的 UB:

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

对于 va_arg 宏,给出了具有不同符号的相同类型的异常(exception)情况,但对于 printf() 则没有,并且不要求 printf() 使用 va_arg (4)。

脚注: (用 (n) 标记)

  1. 这意味着 INT_MAX==SCHAR_MAX,因为 char 没有填充。

  2. 另请参阅此问题:Is unsigned char always promoted to int?

  3. 相同的规则适用于 printf(),请参阅 C99 7.19.6.3:2

  4. 另请参阅此问题:Does printf("%x",1) invoke undefined behavior?

最佳答案

程序可以有或没有未定义的行为取决于实现的特征

例如,执行的程序

int x = 32767;
x++;

(并且在其他方​​面已明确定义)在 INT_MAX > 32767 的实现上具有明确定义的行为,否则具有未定义的行为。

您的程序:

#include <stdio.h>

int main(void)
{
  char a='A';
  printf("%c\n",a);
  return 0;
}

对于 INT_MAX >= CHAR_MAX 的任何托管实现都有明确定义的行为。在任何此类实现中, 'A' 的值晋升为int ,这就是%c预计。

如果INT_MAX < CHAR_MAX (这意味着 char 是无符号的,并且 CHAR_BIT >= 16 ), a 的值晋升为unsigned int 。 N1570 7.21.6.1p9:

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

暗示这有未定义的行为。

实际上,(a) 这样的实现很少见,可能不存在(我听说过的 CHAR_BIT > 8 的唯一现有 C 实现是针对 DSPs 的,并且这样的实现很可能是独立的),并且 (b)任何此类实现都可能被设计为优雅地处理此类情况。

关于c - 在 printf 需要 int 的地方给 printf 一个 char 参数是 UB 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63908544/

相关文章:

c++ - int a[] = {1,2,};为什么允许在初始化列表中使用尾随逗号?

c++ - 如果 "delete this"不需要访问 "somethings",那么在 "this"之后做某事是否安全?

c++ - 为什么非可变 lambda 表达式中的字段在捕获常量值或常量引用时使用 "const"?

c++ - 为什么要使用两个运算符来删除动态分配的内存?

C++:奇怪的行为:返回语句的返回值发生变化

c - 使用 malloc(0) 和 memcpy

C 程序卡在运行中

将指针转换为非指针类型

c - Eclipse 和 Yosemite 中的全局环境变量

C strcpy 是否需要特定的缓冲区大小或仍然可以工作?