在表达式p + a中,p是指针类型,a是整数,整数提升规则是否适用?例如,如果a是char,在64位机器上,它肯定会在添加到指针值之前扩展到64位(在编译的程序集中),但它是由标准指定的吗?会提升到什么程度呢?int、intptr_t或ptrdiff_t?unsigned char或size_t将转换为什么?
p + a
p
a
char
int
intptr_t
ptrdiff_t
unsigned char
size_t
50pmv0ei1#
由于char是一个整数类型,因此标准似乎不要求任何升级:
对于加法,两个操作数都应该是算术或无作用域枚举类型,或者一个操作数应该是指向完全定义的对象类型的指针,另一个应该是整数或无作用域枚举类型
看起来实现可能取决于底层架构允许的指针添加类型-因此,如果架构支持address+BYTE-则char一切都很好-如果不支持,则可能会提升到支持的最小地址偏移量大小。指针减法的结果被定义为“std::ptrdiff_t”类型
address+BYTE
当两个指向同一数组对象的元素的指针相减时,结果是两个数组元素的下标之差。结果的类型是实现定义的有符号整数类型;此类型应与标头中定义为std::ptrdiff_t的类型相同
lzfw57am2#
C11 §5.7/1:加法运算符+和-从左到右分组。通常的算术转换是对算术或枚举类型的操作数执行的.”这显然将问题简化为考虑通常的算术转换,由...定义。C11 §5/9:“许多需要算术或枚举类型操作数的二进制运算符会导致转换并以类似的方式生成结果类型。目的是产生一个公共类型,这也是结果的类型。这种模式称为 * 通常的算术转换 *,定义如下:
+
-
long double
double
float
机械地遵循,这组规则将在最后一个项目符号点(标准中的破折号)结束,并将指针操作数转换为对应于不存在的东西的无符号整数类型。这是不对的因此,措辞“通常的算术转换是针对算术或枚举类型的操作数执行的”不能按字面解释-它是有缺陷的-但必须解释为“通常的算术转换是针对两个操作数都是算术或枚举类型的调用执行的”。因此,* promotion * 本身,通过通常的算术转换调用,当一个操作数是指针时,不会起作用。但在第5.7节中,我们发现...C++11 §5.7/5:当一个整型的表达式与指针相加或相减时,结果的类型就是指针操作数的类型。如果指针操作数指向数组对象的一个元素,并且数组足够大,则结果指向从原始元素偏移的元素,使得结果和原始数组元素的下标之差等于整数表达式。这完全根据数组索引来定义结果。对于char数组,下标的差值可以超过ptrdiff_t的范围。一种合理的实现方式是将非指针参数转换为无符号整数类型size_t(实际上是位级别的符号扩展),并使用该值与模运算来计算结果指针值。
1tuwyuhd3#
我会说普通的整数提升应用于a。C标准没有提供任何特定的规则来转换指针上算术运算的整数部分。也就是说,当a被声明为char时,它在传递给+运算符之前被转换为int。如果添加一个size_t,它要么保持size_t的定义,要么如果(无论出于何种原因)它的秩比int小,它将被提升为int。
1tuwyuhd4#
是的,在C++标准(第5.7节加法运算符第1段)中规定对算术或枚举类型的操作数执行通常的算术转换。对于秩小于int的类型(例如char或unsigned char),将执行整数提升。对于size_t(size_t的秩不小于int或unsigned int的秩),由于没有算术类型的第二个操作数,因此不会执行任何操作。
unsigned int
4条答案
按热度按时间50pmv0ei1#
由于
char
是一个整数类型,因此标准似乎不要求任何升级:对于加法,两个操作数都应该是算术或无作用域枚举类型,或者一个操作数应该是指向完全定义的对象类型的指针,另一个应该是整数或无作用域枚举类型
看起来实现可能取决于底层架构允许的指针添加类型-因此,如果架构支持
address+BYTE
-则char
一切都很好-如果不支持,则可能会提升到支持的最小地址偏移量大小。指针减法的结果被定义为“std::ptrdiff_t”类型
当两个指向同一数组对象的元素的指针相减时,结果是两个数组元素的下标之差。结果的类型是实现定义的有符号整数类型;此类型应与标头中定义为std::ptrdiff_t的类型相同
lzfw57am2#
C11 §5.7/1:
加法运算符
+
和-
从左到右分组。通常的算术转换是对算术或枚举类型的操作数执行的.”这显然将问题简化为考虑通常的算术转换,由...定义。
C11 §5/9:
“许多需要算术或枚举类型操作数的二进制运算符会导致转换并以类似的方式生成结果类型。目的是产生一个公共类型,这也是结果的类型。这种模式称为 * 通常的算术转换 *,定义如下:
long double
,则另一个操作数应转换为long double
。double
,则另一个操作数应转换为double
。float
,则另一个操作数应转换为float
。机械地遵循,这组规则将在最后一个项目符号点(标准中的破折号)结束,并将指针操作数转换为对应于不存在的东西的无符号整数类型。这是不对的因此,措辞“通常的算术转换是针对算术或枚举类型的操作数执行的”不能按字面解释-它是有缺陷的-但必须解释为“通常的算术转换是针对两个操作数都是算术或枚举类型的调用执行的”。
因此,* promotion * 本身,通过通常的算术转换调用,当一个操作数是指针时,不会起作用。
但在第5.7节中,我们发现...
C++11 §5.7/5:
当一个整型的表达式与指针相加或相减时,结果的类型就是指针操作数的类型。如果指针操作数指向数组对象的一个元素,并且数组足够大,则结果指向从原始元素偏移的元素,使得结果和原始数组元素的下标之差等于整数表达式。
这完全根据数组索引来定义结果。对于
char
数组,下标的差值可以超过ptrdiff_t
的范围。一种合理的实现方式是将非指针参数转换为无符号整数类型size_t
(实际上是位级别的符号扩展),并使用该值与模运算来计算结果指针值。1tuwyuhd3#
我会说普通的整数提升应用于
a
。C标准没有提供任何特定的规则来转换指针上算术运算的整数部分。也就是说,当
a
被声明为char
时,它在传递给+
运算符之前被转换为int
。如果添加一个
size_t
,它要么保持size_t
的定义,要么如果(无论出于何种原因)它的秩比int
小,它将被提升为int
。1tuwyuhd4#
是的,在C++标准(第5.7节加法运算符第1段)中规定
对算术或枚举类型的操作数执行通常的算术转换。
对于秩小于
int
的类型(例如char
或unsigned char
),将执行整数提升。对于size_t
(size_t
的秩不小于int
或unsigned int
的秩),由于没有算术类型的第二个操作数,因此不会执行任何操作。