Здесь я взял две локальные переменные и распечатал их адреса. Я получаю оба адреса одинаково, как? код находится здесь: int main (int argc, char const * argv []) {char str [150]; char arr [] ...

0
Jignesh Parmar 6 Янв 2021 в 20:44

1 ответ

Лучший ответ

В char arr[][15]={0}; пустой нижний индекс предоставляет компилятору вычислить количество элементов. Единственное начальное значение инициализирует arr[0][15], после чего компилятор устанавливает остальные элементы arr[0] в ноль. Поскольку для arr[1] нет инициализаторов, компилятор устанавливает размер массива равным 1 элементу, поэтому arr[0] существует, а arr[1] - нет.

В printf arr[1] номинально относится к массиву, поэтому компилятор автоматически преобразует его в указатель на свой первый элемент, &arr[1][0]. Хотя поведение не определено стандартом C, это номинально просит вычислить, где этот элемент будет. Конечно, если бы он существовал, то сразу после окончания arr[0]. Поскольку компилятор поместил str сразу после arr, str находится на том месте, где будет arr[1][0], поэтому вычисление дает тот же адрес.

Существует несколько причин, по которым компиляция и выполнение одного и того же исходного кода может дать разные ответы, в том числе то, что компилятор может поместить str в другое место относительно arr и тот факт, что поведение использования {{X2} } не определено, значит, компилятор может неожиданным образом преобразовать его во время оптимизации.

Тем не менее, программа может быть изменена, чтобы иметь (в основном) определенное поведение, изменив printf на:

printf("---str:[%p]---arr0:[%p]---arr1:[%p]\n",
    (void *) str, (void *) &arr[0], (void *) &arr[1]);

Хотя &arr[1], похоже, относится к несуществующему объекту, C 2018 6.5.3.2 3 приводит к тому, что он обрабатывается как arr+1, а 6.5.6 8 позволяет нам вычислить адрес сразу за последним элементом в массиве. Таким образом, поведение этого printf достаточно определено, чтобы печатать указанные адреса.

В этом случае адрес, напечатанный для str, будет равен адресу, напечатанному для &arr[1], если str следует за arr в памяти.

1
Eric Postpischil 6 Янв 2021 в 18:11