繁体   English   中英

C指针上的一元加法如何工作?

[英]How does unary addition on C pointers work?

我知道一元运算符++将一个加到一个数字上。 但是,我发现如果我在一个int指针上执行它,它会递增4(我的系统上的int的sizeof)。 为什么这样做? 例如,以下代码:

int main(void)
{
  int *a = malloc(5 * sizeof(int));
  a[0] = 42;
  a[1] = 42;
  a[2] = 42;
  a[3] = 42;
  a[4] = 42;
  printf("%p\n", a);
  printf("%p\n", ++a);
  printf("%p\n", ++a);
  return 0;
}

将返回三个数字,每个数字之间相差4。

这就是C的方式 - 完整的解释在规范中, 第6.5.6节“附加算子” ,第8段:

当一个具有整数类型的表达式被添加到指针或从指针中减去时,结果具有指针操作数的类型。 如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向偏离原始元素的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式。 -th and i -th elements of the array object, provided they exist. 换句话说,如果表达式P指向数组对象的第i个元素,则表达式(P)+N (等效地, N+(P) )和(P)-N (其中N具有值n )指向分别为数组对象的第i + 和第i - 个元素,只要它们存在即可。 此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向一个超过数组对象的最后一个元素,如果表达式Q指向一个超过数组对象的最后一个元素,表达式(Q)-1指向数组对象的最后一个元素。 如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义。 如果结果指向数组对象的最后一个元素之后,则不应将其用作已计算的一元*运算符的操作数。

要将它与您使用前缀++运算符联系起来,您还需要阅读第6.5.3.1节“前缀增量和减量运算符” ,第2段:

前缀++运算符的操作数的值递增。 结果是增量后操作数的新值。 表达式++E等价于(E+=1)

第6.5.16.2节“复合转让 ”第3段:

E1 op = E2形式的复合赋值与简单赋值表达式E1 = E1 op (E2)仅在于左值E1仅被评估一次。

它将指针位置增加int的大小,即指针的声明类型。

请记住, int *只是指向内存中某个位置的指针,您可以在其中存储“int”。 当你指向++ ,它会将它移动一个位置(按类型的大小),在这种情况下,它会使你的值“4”更高,因为sizeof(int)==4

这样做的原因是使以下陈述成立:

*(ptr + n) == ptr[n]

这些可以互换使用。

在指针运算中,向指针添加一个将添加它指向的类型的大小。

所以对于给定的:

TYPE * p;

添加到p实际上会增加sizeof(TYPE) 在这种情况下,int的大小为4。

看到这个相关的问题

因为在“C”中,指针算术总是按指向的对象的大小进行缩放。 如果你仔细想一想,事实证明这是“正确的事情”。

它这样做是为了让你不开始访问它中间的整数。

因为指针不是引用;)。 它不是一个值,它只是内存中的一个地址。 检查指针的值时,它将是一个数字,可能很大,与存储在该存储器位置的实际值无关。 比如, printf("%p\\n", a); 打印“2000000” - 这意味着您的指针指向机器内存中的第2000000个字节。 它几乎没有意识到它存储在什么价值。

现在,指针知道它指向的类型。 在您的情况下为整数。 由于一个整数是4个字节长,当你想要跳转到指针所指向的下一个“单元格”时,它需要是2000004.这是1个整数,所以a++非常有意义。

顺便说一句,如果你想获得42 (从你的例子),打印出指向的值: printf("%d\\n", *a);

我希望这是有道理的 ;)

这很简单,因为它归结为指针,在你的情况下是一个整数指针,一元增量意味着由一个单元增加内存位置,其中一个单元=整数的大小。

这个整数大小取决于从编译到编译器,对于32位和16位,它是4字节,而对于64位编译器,它是8字节。

尝试使用字符数据类型执行相同的程序,当字符占用1个字节时,它将给出1个字节的差异。

简而言之,您遇到的4的差异是内存中SIZE OF ONE INTEGER的差异。

希望这有所帮助,如果不是,我会很乐意帮助我告诉我。

“为什么这样做?” 为什么你会期望它做任何其他事情? 递增一个点使它指向它指向的类型的下一个项目。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM