Когда вы думаете о указателях, это помогает рисует диаграммы. Указатель - это стрелка, указывающая на адрес в памяти, с меткой, указывающей тип значения. Адрес указывает, где искать, и тип указывает, что делать. Наведение указателя изменяет метку на стрелке, но не там, где указана стрелка.
d
в main
является указателем на c
, который имеет тип char
. A char
- один байт памяти, поэтому, когда d
разыменовывается, вы получаете значение в этом байте памяти. На приведенной ниже диаграмме каждая ячейка представляет один байт.
-+----+----+----+----+----+----+-
| | c | | | | |
-+----+----+----+----+----+----+-
^~~~
| char
d
Когда вы приводите d
к int*
, вы говорите, что d
действительно указывает на int
значение. В большинстве систем сегодня int
занимает 4 байта.
-+----+----+----+----+----+----+-
| | c | ?₁ | ?₂ | ?₃ | |
-+----+----+----+----+----+----+-
^~~~~~~~~~~~~~~~~~~
| int
(int*)d
Когда вы разыменования (int*)d
, вы получаете значение, которое определяется из этих четырех байтов памяти. Значение, которое вы получаете, зависит от того, что находится в этих ячейках с пометкой ?
, а также о том, как int
представлен в памяти.
ПК является little-endian, что означает, что значение из int
вычисляется следующим образом (при условии, что оно охватывает 4 байта): * ((int*)d) == c + ?₁ * 2⁸ + ?₂ * 2¹⁶ + ?₃ * 2²⁴
. Таким образом, вы увидите, что в то время как значение является мусором, если вы печатаете в шестнадцатеричном формате (printf("%x\n", *n)
), последние две цифры всегда будут 35
(это значение символа '5'
).
Некоторые другие системы являются большими и упорядочивают байты в другом направлении: * ((int*)d) == c * 2²⁴ + ?₁ * 2¹⁶ + ?₂ * 2⁸ + ?₃
. В этих системах вы обнаружите, что значение всегда начинает с 35
при печати в шестнадцатеричном формате. Некоторые системы имеют размер int
, который отличается от 4 байтов. Редкие несколько систем упорядочивают int
по-разному, но вы вряд ли встретите их.
В зависимости от вашего компилятора и операционной системы вы можете обнаружить, что при каждом запуске программы значение различно или что оно всегда одно и то же, но изменяется, когда вы делаете даже незначительные изменения в исходном коде.
В некоторых системах значение int
должно храниться в адресе, кратном 4 (или 2 или 8). Это называется требованием alignment. В зависимости от того, правильно ли выровнен адрес c
, программа может выйти из строя.
В отличие от вашей программы, вот что произойдет, если у вас есть значение int
и возьмите указатель на него.
int x = 42;
int *p = &x;
-+----+----+----+----+----+----+-
| | x | |
-+----+----+----+----+----+----+-
^~~~~~~~~~~~~~~~~~~
| int
p
Указатель p
указывает на int
значение. Метка на стрелке правильно описывает, что находится в ячейке памяти, поэтому нет сюрпризов при разыменовании.
INT имеет больший размер, чем полукокс, так это чтение вне пространства «5» символа. Попробуйте сделать то же самое, используя меньший тип данных (int c, printf "% c") – SheetJS
Значение '* n' будет' int', которое должно быть 4 байта. '* n' указывает на локальную переменную' c' в 'main()'. Это означает, что вы будете записывать значение '' c'' и все три байта следуют за ним в памяти. (Мое предположение - значение 'd'.) Вы можете проверить это, записав номер в шестнадцатеричном формате - две цифры должны быть одинаковыми каждый раз. – millimoose
'' 5'' - вы думаете, что это выглядит как int, поскольку оно кажется числом, но это всего лишь символ, который представляет цифру. 5. – mah