Каким образом адрес массива равен своему значению в C?

В следующем бите кода значения указателя и адреса указателя отличаются как ожидалось.

Но значения массива и адреса не делают!

Как это может быть?

Вывод

my_array = 0022FF00
&my_array = 0022FF00
pointer_to_array = 0022FF00
&pointer_to_array = 0022FEFC
#include <stdio.h>

int main()
{
  char my_array[100] = "some cool string";
  printf("my_array = %p\n", my_array);
  printf("&my_array = %p\n", &my_array);

  char *pointer_to_array = my_array;
  printf("pointer_to_array = %p\n", pointer_to_array);
  printf("&pointer_to_array = %p\n", &pointer_to_array);

  printf("Press ENTER to continue...\n");
  getchar();
  return 0;
}
179
задан phant0m 7 January 2013 в 14:25
поделиться

3 ответа

Имя массива обычно соответствует адресу первого элемента массива, поэтому array и & array имеют одинаковое значение (но разные типы, поэтому array + 1 и & array + 1 будут не равными, если массив состоит из более чем 1 элемента. ).

Есть два исключения из этого: когда имя массива является операндом sizeof или унарным & (адрес-of), имя относится к самому объекту массива. Таким образом, sizeof array дает вам размер всего массива в байтах, а не размер указателя.

Для массива, определенного как T array [size] , он будет иметь тип T * . Когда / если вы увеличиваете его, вы переходите к следующему элементу в массиве.

& array вычисляет тот же адрес, но с тем же определением создает указатель типа T (*) [size] - то есть это указатель на массив, ни к одному элементу. Если вы увеличите этот указатель, он добавит размер всего массива, а не размер отдельного элемента. Например, с таким кодом:

char array[16];
printf("%p\t%p", (void*)&array, (void*)(&array+1));

Мы можем ожидать, что второй указатель будет на 16 больше, чем первый (потому что это массив из 16 символов). Поскольку% p обычно преобразует указатели в шестнадцатеричное, это может выглядеть примерно так:

0x12341000    0x12341010
201
ответ дан 23 November 2019 в 20:12
поделиться

Это потому, что имя массива ( my_array ) отличается от указателя на массив. Это псевдоним адреса массива, и его адрес определяется как адрес самого массива.

Однако указатель является обычной переменной C в стеке. Таким образом, вы можете взять его адрес и получить значение, отличное от адреса, который он содержит внутри.

Я писал на эту тему здесь - посмотрите, пожалуйста.

29
ответ дан 23 November 2019 в 20:12
поделиться

В Си, когда вы используете имя массива в выражении (включая передачу его в функцию), если оно не является операндом оператора address-of (&) или оператора sizeof, оно распадается на указатель на его первый элемент.

То есть в большинстве контекстов array эквивалентен &array[0] как по типу, так и по значению.

В вашем примере my_array имеет тип char[100], который распадается на char*, когда вы передаете его в printf.

&my_array имеет тип char (*)[100] (указатель на массив из 100 char). Поскольку он является операндом к &, это один из случаев, когда my_array не сразу распадается на указатель на его первый элемент.

Указатель на массив имеет то же значение адреса, что и указатель на первый элемент массива, поскольку объект массива - это просто непрерывная последовательность его элементов, но указатель на массив имеет тип, отличный от указателя на элемент этого массива. Это важно, когда вы выполняете арифметику указателя на два типа указателей.

pointer_to_array имеет тип char * - инициализируется для указания на первый элемент массива, поскольку именно на него распадается my_array в выражении инициализатора - и &pointer_to_array имеет тип char ** (указатель на указатель на char).

Из них: my_array (после разложения на char*), &my_array и pointer_to_array все указывают непосредственно либо на массив, либо на первый элемент массива и поэтому имеют одинаковое значение адреса.

26
ответ дан 23 November 2019 в 20:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: