C 在';对于';循环初始值设定项创建分段错误

C 在';对于';循环初始值设定项创建分段错误,c,for-loop,pointers,declaration,C,For Loop,Pointers,Declaration,我在for循环中使用指针时遇到问题。在我的for循环初始值设定项中,我取消对int指针的引用,并给它一个值“0”。当我在循环中使用解引用的指针时,我得到了一个分段错误,我不明白为什么。我正在使用和C GNU GCC编译器 查看watch窗口,我可以看到在for循环期间,变量有一个随机数 在for循环期间,取消引用的指针似乎失去了作用域 守则: #include <stdio.h> int main(void) { int val = 0; int *p = NULL

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

  • 查看watch窗口,我可以看到在
    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;
    }
    
    #包括
    内部主(空)
    {
    int-val=0;
    int*p=NULL;
    int-answer=0;
    p=&val;
    *p=1;//此操作成功取消引用并设置为1
    对于(inti=3,(*p)=0;i>=0;i--)//这里*p是一个随机数
    {
    printf(“做事”);
    (*p)+=1;//这里它会导致分段错误
    }
    答案=*p;
    }
    

    我想用我现在的方式使用指针不会有问题。

    仔细看看这里:

    for (int i=3, (*p)=0 ; i>=0; i--)
    
    for
    的第一部分中,您定义了一个名为
    p
    新的指针变量,该变量对前面定义的
    p
    进行阴影处理,并将其初始化为空。然后取消对循环中导致segfault的NULL指针的引用

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

    *p = 0;
    for (int i=3; i>=0; i--)
    
    int i;
    for (i=3, (*p)=0 ; i>=0; i--)
    
    或者您可以在循环外部定义
    i

    *p = 0;
    for (int i=3; i>=0; 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
    和一个
    int*p
    ,它指向地址0。这与前面定义的
    p
    不同。它只是阴影。因此,当您取消引用它时,您会得到segfault。

    提示:使用
    -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;
          |          ^
    

    在循环外声明
    i
    ,并使用
    for(i=3,*p=0;i>=0…
    ,因为他们使用了GCC,所以可能值得注意的是,
    GCC-Wshadow
    会对此发出警告。