Могу ли я объявить указатель C с инициализацией по собственному адресу?
void* p = &p;
Меня особенно беспокоит, соответствует ли это строго стандарту C23 (в нынешнем виде).
Я предполагаю, что этот вопрос эквивалентен тому, работает ли следующее, что ближе к моему фактическому варианту использования:
typedef struct st {
void* p;
} st;
st x = { .p = &x };
Из любопытства: как вы это используете?
Вариант использования — это функция для загрузки каталогов, которая принимает структуру, чтобы указать допустимое содержимое и описать, как его загрузить. Для подкаталога эта структура указывает на другую структуру своего типа, управляющую загрузкой подкаталога. Я загружаю каталог, требования к которому точно такие же, как и к подкаталогу, поэтому я хочу, чтобы структура, которую я определяю для управления загрузкой, указывала на себя как структуру для управления загрузкой подкаталога.
Да, это абсолютно законно, почему бы и нет?
Моя причина сомневаться в его законности заключается в том, что перед объявлением переменная не определена, поэтому, если бы язык считал, что выражение инициализации находится до объявления, это было бы недопустимо.
Все должно быть в порядке. Я не могу придумать ни одной части стандарта, которая делала бы это недействительным, и C23 также не привнес ничего нового, что бы это изменило.
Наиболее актуальной частью стандарта будет 6.6, касающаяся адресных констант, используемых в качестве инициализаторов (из проекта C23 N3096):
Константа адреса — это нулевой указатель, указатель на lvalue, обозначающий объект статического хранилища. продолжительность или указатель на указатель функции; он должен быть создан явно с использованием унарного
&
оператор или целочисленную константу, приведенную к типу указателя, или неявно используя выражение массива или тип функции.Операторы индекса массива
[]
и доступа к члену->
, унарные операторы адреса&
и косвенности*
, а также приведения указателей могут использоваться при создании адресной константы, но доступ к значению объекта с помощью этих операторов невозможен. .
Новым в C23 является следующее, в основном связанное с ситуациями constexpr
и составными литералами:
Константа структуры или объединения — это именованная константа или составная константа-литерал со структурой или типом объединения соответственно.
Реализация может принимать другие формы константных выражений; однако они не являются целыми числами постоянное выражение.
Начиная со структуры или константы объединения, оператор доступа к члену
.
может использоваться для формирования именованной константы или составной константы-литерала, как описано выше.
Если оператор доступа к члену.
обращается к члену константы объединения, доступный член должен быть тем же самым, что и член, который инициализируется инициализатором константы объединения.
С практической точки зрения, выходящей за рамки стандарта C, любая объявленная нами переменная должна уже иметь место в памяти до того, как мы ее инициализируем, иначе как программа узнает, где хранить этот инициализатор? (Использование оператора &
также означает, что его нельзя сохранить в регистре.) Стандарт C намеренно расплывчат, когда речь идет о том, где и как переменные хранятся в памяти, поэтому он не охватывает такие вещи, как адреса компоновщика, смещения стека. и тому подобное.
Я думаю, ты сможешь. Если бы он еще не был в области видимости, вы бы получили ошибку при попытке компиляции.