在表达式p + a
中p
是指针类型且a
是整数,整数提升规则是否适用?例如,如果a
是char
,在64位机器上它肯定会在添加到指针值(在编译的程序集中)之前扩展到64位,但它是由标准?什么会被提升? int
,intptr_t
或ptrdiff_t
?将unsigned char
或size_t
转换为什么?
答案 0 :(得分:1)
由于char
是一个整体类型,因此标准似乎不需要进行任何促销:
另外,两个操作数都应具有算术或非范围枚举类型, 或者一个操作数应该是指向完全定义的对象类型的指针,另一个操作数应该具有整数或无范围的枚举类型
似乎实现可能取决于底层架构允许的指针添加类型 - 所以如果架构支持address+BYTE
- char
一切都很好 - 如果没有,它可能会推广到最小地址偏移大小支持。
指针减法的结果定义为`std :: ptrdiff_t'
当减去指向同一数组对象的元素的两个指针时,结果是两个数组元素的下标的差异。结果的类型是实现定义的有符号整数类型;此类型应与标题中定义为std :: ptrdiff_t的类型相同
答案 1 :(得分:1)
C ++11§5.7/ 1:
“添加剂运算符
+
和-
从左到右分组。通常的算术转换是针对算术或枚举类型的操作数执行的。“
这显然减少了考虑通常的算术转换的问题,由...定义
C ++11§5/ 9:
“许多二进制运算符需要算术运算或运算 枚举类型导致转换并产生类似的结果类型 办法。目的是产生一种普通类型,它也是一种类型 结果此模式称为通常的算术转换, 其定义如下:
如果任一操作数是作用域枚举类型(7.2),则不执行任何转换;如果otheroperand的类型不同,那么表达式就是格式错误。
如果任一操作数的类型为
long double
,则另一个操作数应转换为long double
。否则,如果任一操作数为
double
,则另一个操作数应转换为double
。否则,如果任一操作数为
float
,则另一个操作数应转换为float
。否则,应对两个操作数执行整体促销(4.5)。然后,以下规则应适用于提升的操作数:
如果两个操作数具有相同的类型,则无需进一步转换。
否则,如果两个操作数都有有符号整数类型或两者都有无符号整数类型,则具有较小整数转换等级类型的操作数应转换为具有更高等级的操作数的类型。
< / LI>否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的等级,则带有符号整数类型的操作数应转换为带有无符号的操作数的类型整数类型。
否则,如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数应转换为操作数的类型带有符号整数类型。
否则,两个操作数都应转换为与带符号整数类型的操作数类型对应的无符号整数类型。“
机械地跟随,这组规则将在最后一个项目符号(标准中的破折号)中结束,并将指针操作数转换为与不存在的事物对应的无符号整数类型。这是错的。因此,“通常的算术转换是针对算术或枚举类型的操作数执行”的措辞不能按字面解释 - 它是IMHO有缺陷的 - 但必须解释为“通常的算术转换是针对两个操作数都是算术或枚举的调用执行的类型“
因此,当一个操作数是指针时,通过通常的算术转换调用的促销不起作用。
但是在§5.7中进一步下降,人们发现......
C ++11§5.7/ 5:
“当一个具有整数类型的表达式被添加到指针或从指针中减去时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向偏离原始元素的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式。 “
这完全根据数组索引来定义结果。对于char
数组,下标的差异可能会超出ptrdiff_t
的范围。实现安排这个的合理方法是将非指针参数转换为无符号整数类型size_t
(在位级有效地符号扩展),并将该值与模运算一起使用来计算结果指针值。
答案 2 :(得分:0)
我会说正常整数提升适用于a
。 C-Standard没有为指针上的算术运算的整数部分转换提供任何特定的规则。
也就是说,当a
被声明为char
时,它会在传递给int
运算符之前转换为+
。
如果添加了size_t
,则它会保留size_t
定义的内容,或者(由于某种原因)它的排名较小,然后是int
,它会被提升为int
1}}。
答案 3 :(得分:0)
是的,它在C ++标准(第1段第5.7节添加运算符)中指定
对操作数执行通常的算术转换 算术或枚举类型。
对于排名小于int的类型(例如char或unsigned char),将执行整数提升。对于size_t(size_t的排名不小于int或unsigned int的排名),不会做任何事情,因为没有算术类型的第二个操作数。