前增量和后增量的C指针行为

vcudknz3  于 2023-05-16  发布在  其他
关注(0)|答案(7)|浏览(109)

我在做一些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我正在改变ptr的,这是n[0]地址

现在我们来看看下面的场景:

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呢?

mbzjlibv

mbzjlibv1#

表情

*ptr++;

有价值

*ptr

在递增ptr之前,然后ptr自身递增。写下去没有意义

*ptr++;

因为在ptr递增之前为*ptr的表达式的值不被使用。所以实际上这些表达式的结果(表达式-语句)

ptr++;

*ptr++;

都是一样的
对于表达式*++ptr++*ptr,则在此表达式中,*++ptr在第一个ptr处递增(即它将指向数组的第二个元素),然后解引用,其值是第二个元素的值。在这个表达式++*ptr中,首先返回数组的第一个元素的值(即3),然后该值递增,您将获得4。

pb3s4cty

pb3s4cty2#

请检查以下链接:*argv、*argv、*(argv++)和 *(++argv)之间的区别
您需要了解运算符优先级,以便理解这里发生的事情。
++运算符的优先级高于*

emeijp43

emeijp433#

ptr和 *ptr都在返回后递增指针,在第一种情况下,返回ptr所指向的前一个地址,在第二种情况下,返回该地址的值。你没有对结果做任何事情,所以你看不到区别。

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

++*ptr将获得ptr指向的值,递增它,然后返回。

dojqjjoe

dojqjjoe4#

优先顺序也取决于编译器。它可能会根据编译器而改变。最好使用括号以确保输出

rxztt3cl

rxztt3cl5#

由于之前的答案互相矛盾,我发现了。

// 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编译器会抱怨缺少左值,但C++不会。相反,正如预期的那样,它将p递增两次。但是p += 2更好,因为它是可移植的,更容易理解。

gg58donl

gg58donl6#

这是由于C中的运算符优先级。下面的链接可以帮助你
递增或递减运算符的优先级高于解引用运算符。

*ptr++; is similar to *(ptr++)

http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm

4xy9mtcn

4xy9mtcn7#

由于运算符优先级*pt++;*(ptr++);相同,因此它递增指针,然后解引用指针,什么也不做。

相关问题