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被提升为