Разыменование указателя в инициализаторе цикла for вызывает ошибку сегментации
У меня проблема с использованием указателей в цикле for
. В моем инициализаторе цикла for
я разыменовываю указатель int
и присваиваю ему значение "0". Когда я использую этот разыменованный указатель в цикле, я получаю ошибку сегментации, и я не понимаю, почему. Я использую Code :: Blocks и компилятор C GNU GCC.
Глядя в окно наблюдения, я вижу, что во время цикла 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;
}
Я думал, что не будет проблем с использованием указателя, как я.
Ответы
Ответ 1
Внимательно посмотрите здесь:
for (int i=3, (*p)=0 ; i>=0; i--)
В первой части for
вы определяете новую переменную указателя с именем p
, которая затеняет ранее определенный p
, и инициализируете ее как NULL. Затем вы разыменовываете указатель NULL в цикле, который вызывает segfault.
Вы не можете иметь как определение переменной, так и присвоение существующей переменной вместе, вот так, поэтому переместите присвоение *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
, поэтому оно не объявляет новую переменную. Но я не рекомендовал бы это, поскольку это сделало бы Ваш код более трудным для чтения и понимания.
Ответ 2
Вы объявляете совершенно новую переменную с именем 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.
Ответ 3
Совет: используйте -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