在 'for' 循环初始值设定项中取消引用指针会产生分段错误
Dereferencing a pointer in a 'for' loop initializer creates a segmentation fault
我在 for
循环中使用指针时遇到问题。在我的 for
循环初始值设定项中,我解引用了一个 int
指针并给它一个值“0”。当我在循环中使用那个取消引用的指针时,出现分段错误,我不明白为什么。我正在使用 Code::Blocks 和 C GNU GCC 编译器。
看表window我可以看到在for
循环中变量有一个随机数。
似乎解除引用的指针在 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
的第一部分中,您定义了一个名为 p
的 new 指针变量,它隐藏了之前定义的 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;
| ^
我在 for
循环中使用指针时遇到问题。在我的 for
循环初始值设定项中,我解引用了一个 int
指针并给它一个值“0”。当我在循环中使用那个取消引用的指针时,出现分段错误,我不明白为什么。我正在使用 Code::Blocks 和 C GNU GCC 编译器。
看表window我可以看到在
for
循环中变量有一个随机数。似乎解除引用的指针在
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
的第一部分中,您定义了一个名为 p
的 new 指针变量,它隐藏了之前定义的 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;
| ^