C语言中指针的前置和后置增量行为

3

我正在进行一些C指针实验,并试图理解它的行为。以下是我对下面代码的假设。如果我错了,请纠正我。 我有以下代码:

int n[5] = {3,6,9,12,15};   
int *ptr = n;
ptr++;

printf("%d", *ptr);  //Needless to say, the output will be 6

我的假设: 上面的输出结果是6,因为ptr++意味着ptr = ptr + 1,我改变了n[0]地址,也就是ptr


现在我们来看下面的情况:

int n[5] = {3,6,9,12,15};   
int *ptr = n;
*ptr++;

printf("%d", *ptr);  //Why is the output still 6?

我的问题是:我们如何解释*ptr ++?这是什么意思:
* ptr = * ptr + 1或 * * ptr = ptr + 1或 * ptr = ptr + 1或其他?
顺便说一下,当我打印n的值时,它仍然是3,6,9,12,15。
抱歉,第二个问题:
那我们如何解释* ++ptr和++ * ptr呢?

第二段代码应该会给你一个警告,提示你没有使用计算出的值或类似的情况:在递增指针p之前,你对其进行了解引用操作,但是没有对解引用后的值做任何处理。如果你想要递增指向的值,请使用(*ptr)++ - M Oehm
1
每当不明确哪个操作先执行时,使用括号使其明确。 - August Karlstrom
1
@user3437460,实际上只需要一个正确的答案,而这个答案已经给出了。 - Ja͢ck
问一个看似相似的问题是否合理地引起了负分?如果投票者能留下评论来解释他的负分,我会非常感激。 - user3437460
显示剩余3条评论
7个回答

4

表达式

*ptr++;

具有价值
*ptr

在对ptr进行递增操作之前,然后ptr自己进行递增。没有必要写成这样。
*ptr++;

因为在增加ptr之前,表达式*ptr的值没有被使用。因此,实际上这些表达式(表达式语句)的结果是:

ptr++;

并且。
*ptr++;

一样的。

关于表达式*++ptr++*ptr,在表达式*++ptr中,首先将指针ptr自增1 (它将指向数组的第二个元素),然后对其进行解引用,得到的值为第二个元素的值。 在表达式++*ptr中,首先返回数组的第一个元素的值(即3),然后将该值递增,您将获得4。


谢谢你的回答,我正在寻找类似于你的回答,可以解释各种情况。+1。 - user3437460

2

如果++运算符是后缀递增,则其优先级仅高于运算符。如果++运算符是前缀递增,则它与运算符具有相同的优先级。 - SJHowe

1

运算符优先级也取决于编译器。它可能因编译器而异。最好使用括号来确保输出结果。


1

ptr++ 和 *ptr++ 都是在返回之后将指针递增,前者返回 ptr 指向的上一个地址,后者返回该地址中的值。由于您没有对结果进行任何操作,因此您看不到差异。

*++ptr 会先将 ptr 递增,然后返回它现在指向的值。

++*ptr 会获取 ptr 指向的值,将其递增,然后返回。


1
*ptr++ 中,它和 *(ptr++) 是一样的吗?需要确认一下。 - user3437460
1
@user3437460:是的,这两个是等价的。 - twasbrillig

0

由于之前的答案相互矛盾,我自己找到了答案。

// gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04)
#include "stdio.h"

int main()
{
    int array[] = {0,10,20,30,40,50,60};
    int* p = &array[1];
    int r;
    int i = 1;

    r = *p;
    printf("%d, r = *p: r=%d, p points to %d\n", i++, r, *p);
    r = *p++;
    printf("%d, r = *p++: r=%d, p points to %d\n", i++, r, *p);
    r = ++*p;
    printf("%d, r = ++*p: r=%d, p points to %d\n", i++, r, *p);
    r = *++p;
    printf("%d, r = *++p: r=%d, p points to %d\n", i++, r, *p);
    r = ++*p++;
    printf("%d, r = ++*p++: r=%d, p points to %d\n", i++, r, *p);

    // ++p++;
    printf("%d, ++p++: error: lvalue required as increment operand\n", i++);
    // r = *++p++;
    printf("%d, *++p++: error: lvalue required as increment operand\n", i++);
    // (++p)++;
    printf("%d, (++p)++: C error: lvalue required as increment operand\n", i++);
    printf("%d, ++p++: C++ p points to %d\n", i++, *p);

    // ++(p++);
    printf("%d, ++(p++): error: lvalue required as increment operand\n", i++);

     return 0;
}

输出:

1, r = *p: r=10, p points to 10
2, r = *p++: r=10, p points to 20
3, r = ++*p: r=21, p points to 21
4, r = *++p: r=30, p points to 30
5, r = ++*p++: r=31, p points to 40
6, ++p++: error: lvalue required as increment operand
7, *++p++: error: lvalue required as increment operand
8, (++p)++: C error: lvalue required as increment operand
9, ++p++: C++ p points to 60
10, ++(p++): error: lvalue required as increment operand

1 预期的解引用

2 先解引用 p,然后将其递增

3 将 p 指向的位置递增,p 不变

4 先将 p 递增,然后解引用它

5 先递增 p 所指向的内容 (++*p),然后递增 p (p++)

6、7、10 无法递增中间值,因为它没有存储位置。

8、9 是“有趣”的。C 编译器会报告缺少 lvalue,但 C++ 不会。相反,如预期的那样,它会将 p 递增两次。然而,p += 2 更可取,因为它是可移植且更易理解的。


-1

-1
由于运算符优先级的原因,*pt++;*(ptr++);是相同的,因此它会先递增指针,然后对指针进行解引用操作,但不会执行其他操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接