C中* ptr + = 1和* ptr ++之间的区别


122

我刚开始研究C,在做一个有关将指针传递为函数参数的示例时,我发现了一个问题。

这是我的示例代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int* allocateIntArray(int* ptr, int size){
    if (ptr != NULL){
        for (int i = 0; i < size; i++){
            ptr[i] = i;
        }
    }
    return ptr;
}

void increasePointer(int** ptr){
    if (ptr != NULL){
        *ptr += 1; /* <----------------------------- This is line 16 */
    }
}

int main()
{
    int* p1 = (int*)malloc(sizeof(int)* 10);
    allocateIntArray(p1, 10);

    for (int i = 0; i < 10; i++){
        printf("%d\n", p1[i]);
    }

    increasePointer(&p1);
    printf("%d\n", *p1);
    p1--;
    free(p1);
    fgets(string, sizeof(string), stdin);
    return 0;
}

在第16行出现问题,当我修改*ptr+=1*ptr++。预期的结果应该是整个数组和数字1,但是当我使用*ptr++的结果是0。

有没有之间的任何diffirence +=1++?我以为他们都是一样的。


2
请注意,给定的代码不会像您未声明的那样进行编译string
Spikatrix

6
其他注意事项:1)allocateIntArray是一个不好的名字,因为看来您malloc是函数中的数组,但您不是。我建议fillIntArray改为。2)您不使用的返回值allocateIntArray。建议您将返回类型更改为void。3)不应该if (ptr != NULL)在功能increasePointerif (*ptr != NULL)吗?4)malloc不需要强制转换。请参阅上方的Sourav评论。5):for (int i = 0; i < 10; i++){ printf("%d\n", p1[i]); }并且printf("%d\n", *p1); p1--;需要包含在中if(p1 != NULL)。6)string.h未使用。
Spikatrix

9
p+=1就像++p,而不是p++
Kos

5
这个问题是4年前提出的:++的指针是否与+ = 1相同
ren

3
@ren差不多,但是不完全是。链接的问题不涉及解引用运算符,这是OP此处问题的症结所在。
杰森C

Answers:


289

差异是由于运算符的优先级。

后递增运算符的++优先级比解除引用运算符的优先级高*。所以*ptr++等于*(ptr++)。换句话说,后置增量会修改指针,而不是其指向的指针。

赋值运算符的+=优先级比取消引用运算符的优先级低*,因此*ptr+=1等效于(*ptr)+=1。换句话说,赋值运算符修改指针指向的值,并且不更改指针本身。


3
对于初学者来说,一个记忆是之间的相似*p++*++p。后者的运算符优先级很明确,前者的优先级如下。
Walter Tross

21

问题中涉及的3个运算符的优先顺序如下:

后增量++>解除引用*>分配+=

您可以检查此页面以获取有关该主题的更多详细信息。

解析表达式时,在某行上列出的运算符将比在其下一行上列出的任何运算符更严格地(如用括号括起来)绑定到其参数。例如,表达式*p++被解析为*(p++),而不是(*p)++

长话短说,为了*ptr+=1使用后增量运算符表示此分配,您需要在取消引用运算符上添加括号,以使运算优先++(*ptr)++


3
顺便说一句,这是目前唯一包含解决方案的答案...(* ptr)++
hyde

7

让我们用括号显示操作顺序

a + b / c
a + (b/c)

让我们再做一次

*ptr   += 1
(*ptr) += 1

并再次

*ptr++
*(ptr++)
  • 在中*ptr += 1,我们增加指针指向的变量的值。
  • 在中*ptr++,我们在完成整个语句(代码行)之后递增指针,并返回对指针所指向的变量的引用。

后者允许您执行以下操作:

for(int i = 0; i < length; i++)
{
    // Copy value from *src and store it in *dest
    *dest++ = *src++;

    // Keep in mind that the above is equivalent to
    *(dest++) = *(src++);
}

这是用于将一个src阵列复制到另一个dest阵列的常用方法。


“并返回对指针所指向的变量的引用。” C没有参考。
Miles Rout

@MilesRout也许称它为左值可能更准确?但是我不确定如何在不添加术语的情况下放置它。
Mateen Ulhaq '16

3

很好的问题。

在K&R“ C编程语言”“ 5.1指针和地址”中,我们可以找到答案。

“一元运算符*和&的绑定比算术运算符更紧密”

*ptr += 1      //Increment what ptr points to.

“像*和++这样的一元运算符从右到左关联。”

*ptr++        //Increment prt instead of what ptr point to.

//它的工作方式类似于*(ptr ++)。

正确的方法是:

(*ptr)++      //This will work.

这是我第一次对Stack Overflow发表评论。我已经更新了代码格式。^^感谢您的建议。
Nick.Sang

2

* ptr + = 1:ptr指向的增量数据。* ptr ++:递增指针,该指针指向下一个内存位置,而不是指针指向的数据。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.