C и массивы: назначение [Warning] делает указатель из целого без литья
У меня возникают проблемы с указателями и массивами в C. Здесь код:
#include<stdio.h>
int *ap;
int a[5]={41,42,43,44,45};
int x;
int main()
{
ap = a[4];
x = *ap;
printf("%d",x);
return 0;
}
Когда я компилирую и запускаю код, я получаю это предупреждение:
[Предупреждение] присваивание делает указатель из целого без литья [включено по умолчанию]
Для строки номер 9 (ap = a [4];) и сбой терминала. Если я изменю строку 9, чтобы не включать позицию (ap = a;), я не получаю никаких предупреждений, и она работает. Почему это происходит? Я чувствую, что ответ очевиден, но я просто не вижу его.
Ответы
Ответ 1
В этом случае a[4]
- это 5th
целое число в массиве a
, ap
- указатель на целое число, поэтому вы присваиваете целое число указателю и этому предупреждению.
Таким образом, теперь ap
имеет значение 45
и когда вы пытаетесь отменить ссылку на него (выполняя *ap
), вы пытаетесь получить доступ к памяти по адресу 45, который является недопустимым, поэтому ваша программа падает.
Вы должны сделать ap = &(a[4]);
или ap = a + 4;
В c
имен массивов распадается на указатель, так что a
указывает на 1 - й элемент массива.
Таким образом, a
эквивалентно &(a[0])
.
Ответ 2
Что вы делаете: (я использую байты вместо того, чтобы лучше читать)
Вы начинаете с int *ap
и т.д., поэтому ваша память (ваши компьютеры) выглядит так:
-------------- memory used by some one else --------
000: ?
001: ?
...
098: ?
099: ?
-------------- your memory --------
100: something <- here is *ap
101: 41 <- here starts a[]
102: 42
103: 43
104: 44
105: 45
106: something <- here waits x
Давайте посмотрим, что произойдет, когда (напечатайте короткий текст для... print ( "$ d",...)
print a[0] -> 41 //no surprise
print a -> 101 // because a points to the start of the array
print *a -> 41 // again the first element of array
print a+1 -> guess? 102
print *(a+1) -> whats behind 102? 42 (we all love this number)
и т.д., поэтому a [0] совпадает с * a, a [1] = * (a + 1),....
a [n] просто читается легче.
теперь, что происходит в строке 9?
ap=a[4] // we know a[4]=*(a+4) somehow *105 ==> 45
// warning! converting int to pointer!
-------------- your memory --------
100: 45 <- here is *ap now 45
x = *ap; // wow ap is 45 -> where is 45 pointing to?
-------------- memory used by some one else --------
bang! // dont touch neighbours garden
Таким образом, "предупреждение" - это не просто предупреждение, это серьезная ошибка.
Ответ 3
int[]
и int*
представляются одинаково, за исключением того, что int [] выделяет (IIRC).
ap
является указателем, поэтому его значение целое является опасным, так как вы понятия не имеете, что по адресу 45.
когда вы пытаетесь получить к нему доступ (x = *ap
), вы пытаетесь получить доступ к адресу 45, который вызывает сбой, поскольку он, вероятно, не является частью памяти, к которой вы можете получить доступ.