在 'for' 循环初始值设定项中取消引用指针会产生分段错误

Dereferencing a pointer in a 'for' loop initializer creates a segmentation fault

我在 for 循环中使用指针时遇到问题。在我的 for 循环初始值设定项中,我解引用了一个 int 指针并给它一个值“0”。当我在循环中使用那个取消引用的指针时,出现分段错误,我不明白为什么。我正在使用 Code::Blocks 和 C GNU GCC 编译器。

  1. 看表window我可以看到在for循环中变量有一个随机数。

  2. 似乎解除引用的指针在 for 循环期间失去了作用域。

代码:

#include <stdio.h>

int main(void)
{
    int val = 0;
    int *p = NULL;
    int answer = 0;

    p = &val;

    *p = 1; // This dereferences and sets to one successfully

    for (int i=3, (*p)=0 ; i>=0; i--) // Here *p is a random number
    {
        printf("do stuff");
        (*p) += 1; // Here it causes a segmentation fault
    }
    answer = *p;
}

我认为像我这样使用指针不会有问题。

仔细看这里:

for (int i=3, (*p)=0 ; i>=0; i--)

for 的第一部分中,您定义了一个名为 pnew 指针变量,它隐藏了之前定义的 p并将其初始化为 NULL。然后,您在导致段错误的循环中取消引用 NULL 指针。

您不能像那样同时拥有变量定义和对现有变量的赋值,因此将 *p 的赋值移动到循环之前:

*p = 0;
for (int i=3; i>=0; i--)

或者您可以在循环外定义 i

int i;
for (i=3, (*p)=0 ; i>=0; i--)

可以通过滥用逗号运算符将它们挤在一起:

for (int i=(*p=0,3) ; i>=0; i--)

此处对 p 的赋值作为 i 的初始化程序的一部分发生,因此它不会声明新变量。但我不推荐这样做,因为它会使您的代码更难阅读和理解。

您正在声明一个名为 p 的全新变量:

for (int i=3, (*p)=0 ; i>=0; i--)

这等同于:

for (int i=3, *p=0 ; i>=0; i--)

因此您正在创建一个 int i 和一个指向地址 0 的 int *p。这与之前定义的 p 不同。它只是遮蔽它。所以当你取消引用它时,你会得到段错误。

提示:使用 -Wshadow 可在变量遮挡另一个变量时收到警告。

[] $ gcc main.c -Wshadow
main.c: In function ‘main’:
main.c:13:21: warning: declaration of ‘p’ shadows a previous local [-Wshadow]
   13 |     for (int i=3, (*p)=0 ; i>=0; i--) // Here *p is a random number
      |                     ^
main.c:6:10: note: shadowed declaration is here
    6 |     int *p = NULL;
      |          ^

https://coliru.stacked-crooked.com/a/5de37f53cf0b094d