C语言:递增传递给函数的指针地址 ++ 运算符

5

我有一个问题是从这个讨论中引申出来的:C - 修改传递给函数的指针的地址

假设我有以下代码:

#include <stdio.h>
foo(char **ptr){
    *ptr++;
}

int main()
{

    char *ptr = malloc(64);
    char arr[] = "Hello World!";
    memcpy(ptr, arr, sizeof(arr)); 
    foo(&ptr);
    foo(&ptr);
    printf("%s",ptr);
    return 0;
}

我想知道这个程序的输出结果,我认为应该是llo World!

经过一番调查后,我发现了上面链接中的问题,并意识到在C语言中,函数参数总是按传递。到目前为止还没有问题。当我们将*ptr++;表达式改成*ptr = *ptr +1;时,输出结果变成了:llo World!

此时,我有点困惑。为了更改指针地址,我们需要一个双重指针。这是可以理解的,但后增量运算符为什么不同呢?是因为运算符优先级的原因吗?

在这里,我在一个在线C编译器中尝试了这个例子。

3个回答

3
后缀递增运算符++的优先级高于解引用运算符*。 所以这样做:
*ptr++;

解析为:
*(ptr++);

因此它会改变参数值本身,而不是它所指向的值。你需要这样:

(*ptr)++;

1
@asevindik 前缀递增与解引用具有相同的优先级。后缀优先级更高。 - dbush
我会将此评论标记为已接受的答案。然而,正如其他人在下面所述,++*ptr也是解决此问题的另一种方法。对我来说,更好、更清晰的陈述是*ptr = *ptr+1;。谢谢! - asevindik

3
后缀运算符的优先级高于一元运算符。因此这个表达式
*ptr++

等同于

*( ptr++ )

子表达式 ptr++ 的值是其递增之前指针的值。

实际上,您正在递增类型为 char ** 的参数 ptr。因此,这种递增不会改变原始指针,也没有意义。

相反,您可以写成:

( *ptr )++

但是使用一元递增运算符会更清晰,更不容易混淆,例如:

++*ptr

如果你想要增加原始指针本身。


2

正如其他人所解释的那样,++ 的优先级高于 *,因此您的函数 foo 实际上被编译为:

foo (char **ptr) {
    ptr = ptr + 1; // This modifies the parameter, which is a copy of a variable, copied *specifically* for this function; hence, modifying it will have no effect outside of the function.
    *ptr; // This is just an expression; it doesn't actually do anything, as the compiler would tell you if you wrote it this way.
}

如果您将*ptr++更改为(*ptr)++,该函数将按以下方式工作:
foo (char **ptr) {
    *ptr = *ptr + 1; // Sets the variable pointed to by ptr to be equal to itself plus one.
}

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