我刚刚开始研究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;
}
当我将*ptr+=1
修改为*ptr++
时,问题出现在第16行。预期结果应该是整个数组和数字1,但是当我使用*ptr++
时,结果为0.
+=1
和++
之间是否存在差异?我以为他们俩都是一样的。
答案 0 :(得分:283)
差异是由于运营商优先。
后增量运算符++
的优先级高于解除引用运算符*
。因此*ptr++
相当于*(ptr++)
。换句话说,后增量会修改指针,而不是它指向的内容。
赋值运算符+=
的优先级低于取消引用运算符*
,因此*ptr+=1
等同于(*ptr)+=1
。换句话说,赋值运算符会修改指针指向的值,而不会更改指针本身。
答案 1 :(得分:21)
您的问题涉及的3位运营商的优先顺序如下:
后增量++
&gt;解除引用*
&gt;作业+=
您可以查看此page以获取有关该主题的更多详细信息。
在解析表达式时,某个行上列出的运算符将比其下方的行上列出的任何运算符更严格地(如同括号)绑定到其参数。例如,表达式
*p++
被解析为*(p++)
,而不是(*p)++
。
长话短说,为了使用后增量运算符表达此赋值*ptr+=1
,您需要将括号添加到取消引用运算符,以使该操作优先于++
,如此 (*ptr)++
强>
答案 2 :(得分:7)
让我们应用括号来显示order of operations
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
数组中的常用方法。
答案 3 :(得分:3)
非常好的问题。
在K&amp; R“C编程语言”“5.1指针和地址”中,我们可以得到答案。
“一元运算符*和&amp;绑定比算术运算符更紧密”
*ptr += 1 //Increment what ptr points to.
“像*和++这样的一元运算符将从右到左关联。”
*ptr++ //Increment prt instead of what ptr point to.
//就像*(ptr ++)。
正确的方法是:
(*ptr)++ //This will work.
答案 4 :(得分:2)
* ptr + = 1:增加ptr指向的数据。 * ptr ++:指向下一个内存位置的增量指针,而不是指针指向的数据。