为啥在执行递增操作之前分配指针值

Posted

技术标签:

【中文标题】为啥在执行递增操作之前分配指针值【英文标题】:why a pointer value is assigned before the increment operation is performed为什么在执行递增操作之前分配指针值 【发布时间】:2019-06-05 18:58:28 【问题描述】:

为什么*p++先把值赋给i再递增p指针,尽管++后自增优先级更高,而且关联性是从右到左的?

int main()

    int a[]=55,66,25,35,45;
    int i;
    int *p=&a;
    printf("%u \n",p);
    i=*p++;
    printf(" %u  %d",p,i);
    printf("\n %d",*p);

    return 0;

4056 4060 55 66

【问题讨论】:

该代码不应该编译。 int *p=&a; 行输入不正确。 如果你想打印一个指针,你需要格式说明符%p,否则你会调用未定义的行为。在修复之前,任何事情都可能发生... int *p=a; 为什么? &apointer-to-int [5],而不是 pointer-to-int。见:C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) @gokulgoku:仅仅因为它运行时没有明显错误并不意味着它是正确的。你应该至少得到几个警告。 数组在需要时会自动衰减为指针:int* p = a; 就是您所需要的。取a 的地址会导致另一种指针类型:int(*p)[5] = &a; 将是正确的... 【参考方案1】:

后缀++ 运算符的语义是表达式p++ 计算为p当前 值,并且作为副作用 @987654324 @ 递增。实际上,i = *p++;

相同
i = *p;
p++;

前缀 ++ 运算符的语义是表达式计算为p 的当前值加一,并作为副作用p递增。 i = *++p; 实际上与

相同
i = *(p + 1);
p++;

优先级控制评估顺序 - 它只控制解析(哪些运算符与哪些操作数分组)。

【讨论】:

【参考方案2】:

在指针和数组如何协同工作方面似乎存在一些误解。

表达式&a 是指向数组本身的指针,类型为int (*)[5]

您似乎期望获得指向第一个元素的指针,即&a[0],或普通的a(因为它衰减为指向数组第一个元素的指针):

int *p = a;

它的工作并不是巧合,因为指向数组的指针恰好指向与第一个元素的位置相同的地址。地址相同,但&a&a[0]的类型不同。这种语义差异确实至关重要。


关于++ 操作符的问题,简单来说就是它的工作原理。

后缀增减运算符的结果是old值。因此,当您执行 p++ 时,您会在增加之前获得 old 指针。

如果我们采取

i = *p++;

它(有点简化)相当于

int *temporary_old_p = p;
p = p + 1;
i = *temporary_old_p;

此外,指针的"%u" 格式无效。要打印void * 指针(确实需要正确的转换),您应该使用"%p" 格式说明符。

格式说明符和参数类型不匹配会导致未定义的行为


关于*(&a + 1) 的问题,让我们画出数组a 在内存中的样子,用几个箭头表示指针:

+------+------+------+------+------+------ |一个[0] |一个[1] |一个[2] |一个[3] |一个[4] | …… +------+------+------+------+------+------ ^ ^ | | &a[0] | | | &a &a + 1

既然&a的类型是int (*)[5],那么&a + 1的类型也应该是int (*)[5]

如果我们取消引用指针&a(如*(&a)),那么我们会得到实际的数组a。数组,如a,衰减为指向其第一个元素&a[0] 的指针。该指针与&a 指向同一个位置(如上面的“绘图”所示)。

如果我们将&a 更改为&a + 1,那么我们会在取消引用中得到*(&a + 1)。它是“第二个”数组(它是否存在)。就像*(&a) 是一个由五个int 组成的数组一样,*(&a + 1) 也是如此。该数组衰减为指向其第一个元素 &(*(&a + 1))[0] 的指针。

或者认为&a 等于&a + 0。然后很容易看出*(&a) 等于*(&a + 0)。我们知道*(&a) 等于a 等于&a[0],这也意味着*(&a + 0) 必须等于&(*(&a + 0))[0]。这应该很容易看出&(*(&a + 1))[0] 可能是什么。

【讨论】:

即使我把它改成 int *p=a;为什么我得到相同的输出? @gokulgoku 在答案中添加了一段解释它。 谢谢我明白了...我还有一个疑问,当我们有 1 到 &a 时,我们在数组结束后到达地址 ..so &a+1 在数组 a 之后给出了一个地址,但为什么*(&a+1) 也给出相同的地址 @gokulgoku 那是因为*(&a + 1) 等于(&a)[1],并且它的类型是一个数组(五个int)。并且与任何数组一样,它衰减 为指向其第一个元素的指针。这与 a 发生的衰减相同。 好吧,我努力了,但我无法理解它,你能帮我更好地理解它吗...谢谢!!

以上是关于为啥在执行递增操作之前分配指针值的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript高级程序设计:基本概念--操作符

自动递增和递减

自动递增值分配为输入,然后使用值从数据库中删除项目;

3.5 操作符

navicat自动递增的原理

小红书---操作符总结