C 打印字符时会进行哪些整体升级?

C 打印字符时会进行哪些整体升级?,c,printf,undefined-behavior,variadic-functions,integer-promotion,C,Printf,Undefined Behavior,Variadic Functions,Integer Promotion,我最近读到 unsigned char x=1; printf("%u",x); 调用未定义的行为,因为由于格式说明符%u,printf需要一个未签名的int。但我仍然想了解这个示例中发生了什么 我认为积分提升规则适用于表达式printf(“%u”,x) 以及由x表示的值 A.6.1整体推广 字符、短整数或整数位字段,无论是否有符号,或 枚举类型的对象,可以在任何可以使用整数的表达式中使用。 如果int可以表示原始类型的所有值,则会转换该值 到int;否则,该值将转换为无符号整数。此过程称为整

我最近读到

unsigned char x=1;
printf("%u",x);
调用未定义的行为,因为由于格式说明符%u,printf需要一个未签名的int。但我仍然想了解这个示例中发生了什么

我认为积分提升规则适用于表达式
printf(“%u”,x)
以及由
x
表示的值

A.6.1整体推广

字符、短整数或整数位字段,无论是否有符号,或 枚举类型的对象,可以在任何可以使用整数的表达式中使用。 如果int可以表示原始类型的所有值,则会转换该值 到int;否则,该值将转换为无符号整数。此过程称为整数 晋升

这里“可能被使用”是什么意思?它的意思是“语法正确”还是“定义行为”

在这个例子中x是如何提升的?我已经读到它被提升为int,但是如果
printf(“%u”,(int x))
仍然是未定义的行为,那么我真的不明白为什么…

如果你的平台的
int
可以代表
无符号字符所不能代表的所有值,那么提升是
int
,否则是
无符号int
。所以这取决于你的平台


至于“为什么”,那是因为您将
x
作为变量参数传递,而变量参数的规则表明标准升级会发生(大概是为了简化实现)。

因为
printf
使用变量参数列表,所以整数升级会应用于其整数参数。在任何普通的C实现中,整数将
无符号字符
转换为
int
。然后,您正在使用
无符号int
的说明符格式化
int
,因此行为未定义

如果说可以在使用整数的地方使用字符,那么与您的语句具有C标准未定义的行为这一事实之间没有冲突。尽管您可以使用字符代替整数,但有关使用
%u
打印内容的规则仍然适用。如果使用字符产生适合说明符的整数,则定义行为。如果使用字符导致不适合说明符的整数,则该行为不由C标准定义


其他地方关于堆栈溢出的讨论得出结论,异国情调的C实现在理论上可能符合C标准,同时具有与
int
类型一样宽的
char
类型(普通、有符号和无符号)。在这种实现中,
int
不能表示
无符号字符的所有值,因此
无符号字符
必须升级为
无符号int
。但是,这样的实现会很奇特和麻烦(尤其是在处理EOF时),在实践中您可能会忽略它。

由于
printf
使用变量参数列表,因此它将通过
va_arg
解包。C++是指<代码> VAYARG < /C>规则的C标准。C99标准规定如下:

va_arg
宏将扩展为具有指定类型和调用中下一个参数值的表达式。参数
ap
应已由
va_start
va_copy
宏初始化(对于相同的
ap
,无需干预调用
va_end
宏)。每次调用
va_arg
宏都会修改
ap
,以便依次返回连续参数的值。参数类型应为指定的类型名称,以便通过将
*
后固定到类型即可获得指向具有指定类型的对象的指针的类型。如果没有实际的下一个参数,或者如果类型与实际下一个参数的类型不兼容(根据默认参数升级进行升级),则行为未定义,但以下情况除外:

  • 一种类型是有符号整数类型,另一种类型是相应的无符号整数类型,值在两种类型中都可以表示
  • 一种类型是指向void的指针,另一种类型是指向字符类型的指针
显然,在确定实际类型和预期类型是否匹配时,会考虑整数升级。有符号与无符号不匹配包含在第一个要点中


由于
x=1
肯定是一个可由
无符号int
表示的值,提升
无符号char
会生成
有符号int
(如果
int\u MAX>=UCHAR\u MAX
)或
无符号int
(如果
int\u MAX
),这是完全合法的。

我认为行为确实是有定义的,因为你提到的原因。@luserdroog:那么你认为“可能被使用”意味着行为应该被定义?还是我没领会你的意思?@lee77是的。你说得对。“可使用”表示允许使用。标准保证其正常工作。善于批判性思考。你在哪里找到它未定义的说法?@luser droog:我在关于stackoverflow的一个问题的倒数第二个答案中找到了它(向下滚动一点):那么你说在上述上下文中“可能被使用”的意思是“语法正确”?或者它有不同的含义吗?升级是平台相关的,合法性不是。因此有两个步骤:首先,整数升级发生,因为x代表整数,printf使用变量参数列表。现在有两种可能性:1)int不能表示无符号字符可以表示的所有值(这相当奇怪)。然后,x被提升为一个定义为的无符号int。2) int可以表示无符号字符可以表示的所有值,因此x被提升为