包含指针算术,是否自动转换为有符号变量的整数?如果是,为什么?
假设我
int *pointer;
int *pointerdiff;
unsigned int uiVal = -1;
pointerdiff = pointer + uiVal // Pointer will contain valid address here.
其中指针是一个指向int的指针,uiVal初始化为-1,然后我发现指针中的地址减少了4.为什么这里不考虑无符号值-1?
答案 0 :(得分:8)
看起来你的指针溢出了。
我们做一些数学运算。假设您使用的是32位计算机,并且指针初始化为0x 12 34 56 78
。然后,我们将unsigned int变量初始化为-1
,即0x FF FF FF FF
。因为它是无符号整数,所以-1
溢出并实际代表4 294 967 295
。
您的指针是一个整数(int*
),因此每个增量实际上将地址递增sizeof int
,在标准x86计算机上为4。所以我们实际上是在添加0x 03 FF FF FF FC
(0x FF FF FF FF * 4
)。
现在让我们将两者加在一起。
0x 00 12 34 56 78
+ 0x 03 FF FF FF FC
-------------------
0x 04 12 34 56 74
当然,这会溢出,因为我们现在有一个40位的值,指针是32位,只能容纳那么多信息。因此,我们在开始时失去了04
。这会产生0x 12 34 56 74
,即0x 12 34 56 78 - 4
。
答案 1 :(得分:3)
是的,整数操作数被提升。但这并不重要。 uiVal
如果是无符号类型,则不能为-1
。可能你做了
unsigned int uiVal = -1;
pointer + uiVal ...
但这与
相同pointer + UINT_MAX ...
如果指针可以容纳的地址范围无法应对此添加,则可能会导致未定义的行为。标准在5.7/4
出于这些运算符的目的,指向非阵列对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型。
当向指针添加或从指针中减去具有整数类型的表达式时,结果具有指针操作数的类型。 如果指针操作数指向数组对象的元素,并且数组足够大,[...]。 如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义。
也就是说,如果结果指针不在同一个数组中或者在结尾之后,或者如果它确实存在但是由溢出引起,则行为是未定义的。
答案 2 :(得分:0)
我认为右操作数被转换为ptrdiff_t类型,这似乎是签名的。