Подтвердить что ты не робот

Мой указатель char указывает на недопустимое значение после того, как он был запущен из int *

Я изучаю язык программирования C, я только начал изучать массивы с указателями. У меня проблема в этом вопросе, я надеюсь, что этот вывод должен быть 5, но это 2. Может ли кто-нибудь объяснить, почему?

int main(){
   int arr[] = {1, 2, 3, 4, 5};
   char *ptr = (char *) arr;
   printf("%d", *(ptr+4));
   return 0;
}
4b9b3361

Ответ 1

Предположим, что небольшая эндианная архитектура, где int - 32 бита (4 байта), отдельные байты int arr[] выглядят следующим образом (младший байт на нижнем адресе. Все значения в шестнадцатеричном формате):

|01 00 00 00|02 00 00 00|03 00 00 00|04 00 00 00|05 00 00 00
char *ptr = (char *) arr;

Теперь ptr указывает на первый байт - так как вы нажали на char*, он обрабатывается массивом char и далее:

|1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5|0|0|0
 ^
 +-- ptr

Затем *(ptr+4) обращается к пятому элементу массива char и возвращает соответствующее значение char:

|1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5|0|0|0
         ^
         +-- *(ptr + 4) = 2

Следовательно, printf() печатает 2.

В системе Big Endian порядок байтов в каждом int отменяется, что приводит к

|0|0|0|1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5
         ^
         +-- *(ptr + 4) = 0

Ответ 2

Это потому, что размер char равен единице, а размер int равен четырем. Это означает, что добавление 4 в ptr приводит к тому, что результат указывает на вторую запись в массиве int.

Если вы скомпилировали это в большой endian, вы бы напечатали 33554432 вместо этого.

Ответ 3

int main(){
 int arr[] = {1,2,3,4,5};
 char *ptr = (char *) arr;
 printf("%d",*(ptr+4));
 return 0;
}

Каждый случай arr имеет размер sizeof(int) (который может быть 4 в вашей реализации).

Так как ptr является указателем на char, арифметика указателя делает ptr + 4 точками 4 байта после &arr[0], что может be &arr[1].

В памяти это выглядит примерно так:

Address | 0 1 2 3 | 4 5 6 7 | ...
Value   |  arr[0] |  arr[1] | ...

Ответ 4

На 32-битной платформе int в четыре раза превышает размер char. Когда вы добавляете 4 в ptr, вы добавляете в 4 раза больше того, что указывает ptr на ptr (что само по себе является местом памяти). Это будет адрес второго элемента в массиве int.

На 64-битной платформе int имеет размер восемь размер char; и ваш результат будет совсем другим.

Чтобы сократить длинный рассказ, ваш код не переносится (также см. Joachim Pileborg answer re endianness), но забавный, чтобы разблокировать.

Ответ 5

То, что вы делаете, определенно не рекомендуется в производственном коде, но, безусловно, отлично подходит для понимания указателей, бросков и т.д. в процессе обучения, поэтому для этого ваш пример замечательный. Итак, почему вы получаете 2. Это потому, что ваш массив представляет собой массив ints, который в зависимости от вашей архитектуры имеет разный размер (в вашем случае sizeof(int) равно 4). Вы определяете ptr как указатель char, char имеет размер 1 байт. Арифметика указателя (то, что вы делаете, когда пишете ptr+4) работает с размером объектов, на которые ссылается указатель, в вашем случае с символами. Таким образом, ptr+4 находится на расстоянии 4 байта от начала вашего массива и, следовательно, на 2-й позиции вашего массива int. Вот и все. Попробуйте ptr+5, вы должны получить 0.

Ответ 6

Поскольку вы скрываете int * до char *, ptr [0] = 1, ptr [4] = 2, ptr [8] = 3, ptr [12] = 4, ptr [16] = 5 и все остальные равны 0. ptr + 4 указывает на 4-й элемент массива ptr. Таким образом, результат равен 2.

Ответ 7

int main(){
 int arr[] = {1,2,3,4,5};
 char *ptr = (char *) arr;
 printf("%d",*(ptr+4));
 return 0;
}

Представьте, что arr хранится по адресу 100 (полностью тупой адрес). Так что у тебя есть: arr[0] хранится по адресу 100. arr[1] хранится по адресу 104. (из-за типа int существует +4) arr[2] хранится по адресу 108. arr[3] хранится по адресу 112. Etc и т.д.

Теперь вы делаете char *ptr = (char *) arr;, поэтому ptr= 100 (то же, что и arr). Следующее утверждение интересно, особенно второй аргумент printf: *(ptr+4). Помните, что ptr= 100. Итак ptr + 4= 104, тот же адрес, что arr[1]! Таким образом, он напечатает значение arr[1], которое равно 2.