#include<stdio.h>
int main()
{
int a = 1, b = 10, c = 2;
int *arr[] = {&a, &b, &c};
printf("%d\n", *arr[arr[1]-arr[0]]);
return 0;
}
Вот я получаю результат 10
. Под выводом здесь я понимаю память для переменной a b c
, выделенная непрерывно. Этот вывод статический или зависит от системы? Могу ли я ожидать такого же результата в другой системе? И гарантировано непрерывное выделение памяти для этих переменных? Здесь я использую компилятор gcc.
Нет никакой необходимости хранить их в памяти, пока не будут задействованы указатели.
Что вы подразумеваете под "this variable"
?
Последовательность соседних элементов обычно называют «непрерывной», а не «непрерывной».
int arr[] = {1, 10, 2};
int *a = &arr[0], *b = &arr[1], *c = &arr[2];
printf("%d\n", arr[b - a]);
может быть вариант
gcc с отключенной оптимизацией приводит к тому, что программа выдает мне ошибку. Поэтому вы даже не можете ожидать, что эта программа будет работать с тем же компилятором в той же системе. Такова природа ошибок неопределенного поведения.
arr[1]-arr[0]
(то есть &b - &a
) приводит к неопределенному поведению вашей программы (UB).
Вычитание двух указателей из разных массивов (или одного за его пределами) — это UB.
Когда вычитаются два указателя, оба должны указывать на элементы одного и того же объекта массива или на один, следующий за последним элементом объекта массива;
C2Xdr § 6.5.6 10
Гарантируется ли непрерывное выделение памяти для переменной в c?
Нет.
Этот вывод статический или зависит от системы?
Нет, это УБ. Иногда система может «работать» так, как хотелось бы, а иногда нет.
Могу ли я ожидать такого же результата в другой системе?
Другая система может отличаться. Даже одна и та же система может отличаться в разных запусках.
А непрерывное выделение памяти для этой переменной гарантировано?
Нет.
@AndrewHenle «Риск» UB в отношении arr[1]-arr[0]
- это CYA. Если бы arr[0] == arr[1]
, arr[1]-arr[0]
нормально. Конечно, если вернуться к &b - &a
, то да, УБ.
А непрерывное выделение памяти для этой переменной гарантировано?
Массивы.
Стандарт С: 6.2.5
Тип массива описывает непрерывно выделенный непустой набор объекты с определенным типом объекта-члена, называемым типом элемента.
И это означает, что тип объекта должен быть размещен в одном блоке памяти (поэтому байты из int
не могут быть распределены по памяти - и переменная типа int
будет храниться в непрерывном фрагменте памяти размером sizeof(int)
).
Но порядок и место хранения разных переменных стандартом не указан, а только их время жизни (длительность хранения).
Гарантируется ли непрерывное выделение памяти для переменной в c?
Пространство для любого конкретного объекта является смежным. Сюда входят агрегатные объекты (структуры и массивы).
В противном случае пространство для коллекций отдельных объектов не гарантированно будет непрерывным, но это довольно сложно проверить, основываясь исключительно на функциях, определенных спецификацией языка. В частности, различия указателей, такие как ваш arr[1]-arr[0]
, определяются только для указателей на конец одного и того же массива или сразу за ним.
Под выводом здесь я понимаю память для переменной
a b c
, выделенная непрерывно.
Это правдоподобный вывод, но его нельзя поддержать только на основе спецификации языка.
Этот вывод статический или зависит от системы? Могу ли я ожидать такого же результата в другой системе?
В спецификации языка нет оснований полагать, что вы увидите то же самое в другой системе или даже последовательно в данной системе.
А непрерывное выделение памяти для этой переменной гарантировано?
Абсолютно нет, за исключением уже описанного. А если вы пишете код, который зависит от непрерывного распределения при других обстоятельствах, тогда ваш код опасно неверен.
УФ. опасно слишком много думать о памяти.
Нет и нет. Компилятор волен выделять его по своему усмотрению, если он удовлетворяет требованиям выравнивания. Он может даже изменить их порядок в памяти. Или полностью оптимизировать.