C语言 指针算法与积分提升

7hiiyaii  于 2023-05-16  发布在  其他
关注(0)|答案(4)|浏览(175)

在表达式p + a中,p是指针类型,a是整数,整数提升规则是否适用?例如,如果achar,在64位机器上,它肯定会在添加到指针值之前扩展到64位(在编译的程序集中),但它是由标准指定的吗?会提升到什么程度呢?intintptr_tptrdiff_tunsigned charsize_t将转换为什么?

50pmv0ei

50pmv0ei1#

由于char是一个整数类型,因此标准似乎不要求任何升级:

对于加法,两个操作数都应该是算术或无作用域枚举类型,或者一个操作数应该是指向完全定义的对象类型的指针,另一个应该是整数或无作用域枚举类型

看起来实现可能取决于底层架构允许的指针添加类型-因此,如果架构支持address+BYTE-则char一切都很好-如果不支持,则可能会提升到支持的最小地址偏移量大小。
指针减法的结果被定义为“std::ptrdiff_t”类型

当两个指向同一数组对象的元素的指针相减时,结果是两个数组元素的下标之差。结果的类型是实现定义的有符号整数类型;此类型应与标头中定义为std::ptrdiff_t的类型相同

lzfw57am

lzfw57am2#

C11 §5.7/1:
加法运算符+-从左到右分组。通常的算术转换是对算术或枚举类型的操作数执行的.”
这显然将问题简化为考虑通常的算术转换,由...定义。
C
11 §5/9:
“许多需要算术或枚举类型操作数的二进制运算符会导致转换并以类似的方式生成结果类型。目的是产生一个公共类型,这也是结果的类型。这种模式称为 * 通常的算术转换 *,定义如下:

  • 如果两个操作数中有一个是限定作用域的枚举类型(7.2),则不执行转换;如果另一个操作数不具有相同的类型,则表达式是病态的。
  • 如果其中一个操作数的类型为long double,则另一个操作数应转换为long double
  • 否则,如果一个操作数是double,则另一个操作数应转换为double
  • 否则,如果一个操作数是float,则另一个操作数应转换为float
  • 否则,将对两个操作数执行整数提升(4.5)。然后将以下规则应用于提升的操作数:
  • 如果两个操作数具有相同的类型,则不需要进一步的转换。
  • 否则,如果两个操作数都具有有符号整数类型或都具有无符号整数类型,则具有较小整数转换秩的类型的操作数将被转换为具有较大秩的操作数的类型。
  • 否则,如果具有无符号整数类型的操作数的秩大于或等于另一操作数的类型的秩,则具有有符号整数类型的操作数将被转换为具有无符号整数类型的操作数的类型。
  • 否则,如果具有有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数的类型的所有值,则具有无符号整数类型的操作数将被转换为具有有符号整数类型的操作数的类型。
  • 否则,两个操作数都应转换为对应于有符号整数类型的操作数类型的无符号整数类型。

机械地遵循,这组规则将在最后一个项目符号点(标准中的破折号)结束,并将指针操作数转换为对应于不存在的东西的无符号整数类型。这是不对的因此,措辞“通常的算术转换是针对算术或枚举类型的操作数执行的”不能按字面解释-它是有缺陷的-但必须解释为“通常的算术转换是针对两个操作数都是算术或枚举类型的调用执行的”。
因此,* promotion * 本身,通过通常的算术转换调用,当一个操作数是指针时,不会起作用。
但在第5.7节中,我们发现...
C++11 §5.7/5:
当一个整型的表达式与指针相加或相减时,结果的类型就是指针操作数的类型。如果指针操作数指向数组对象的一个元素,并且数组足够大,则结果指向从原始元素偏移的元素,使得结果和原始数组元素的下标之差等于整数表达式。
这完全根据数组索引来定义结果。对于char数组,下标的差值可以超过ptrdiff_t的范围。一种合理的实现方式是将非指针参数转换为无符号整数类型size_t(实际上是位级别的符号扩展),并使用该值与模运算来计算结果指针值。

1tuwyuhd

1tuwyuhd3#

我会说普通的整数提升应用于a。C标准没有提供任何特定的规则来转换指针上算术运算的整数部分。
也就是说,当a被声明为char时,它在传递给+运算符之前被转换为int
如果添加一个size_t,它要么保持size_t的定义,要么如果(无论出于何种原因)它的秩比int小,它将被提升为int

1tuwyuhd

1tuwyuhd4#

是的,在C++标准(第5.7节加法运算符第1段)中规定
对算术或枚举类型的操作数执行通常的算术转换。
对于秩小于int的类型(例如charunsigned char),将执行整数提升。对于size_tsize_t的秩不小于intunsigned int的秩),由于没有算术类型的第二个操作数,因此不会执行任何操作。

相关问题