指针算术&签名/未签名转换!

时间:2010-04-05 12:54:20

标签: c pointer-arithmetic

包含指针算术,是否自动转换为有符号变量的整数?如果是,为什么?

假设我

int *pointer; 
int *pointerdiff;
unsigned int uiVal = -1;

pointerdiff = pointer + uiVal // Pointer will contain valid address here.

其中指针是一个指向int的指针,uiVal初始化为-1,然后我发现指针中的地址减少了4.为什么这里不考虑无符号值-1?

3 个答案:

答案 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 FC0x 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类型,这似乎是签名的。