Формальные определения: посмотрите определение «адресной константы»: «Справочник по языку C 6.19»:
Константа адреса - это указатель на объект со статической продолжительностью хранения или указатель нафункция. Вы можете получить их с помощью оператора & или с помощью обычных преобразований имен массивов и функций в указатели, когда они используются в выражениях. Операторы [],., ->, & (address of) и * (разыменование указателя), а также приведение указателей могут использоваться в выражении, если они не требуют доступа к значению какого-либо объекта.
Практический ответ: «C» требует, чтобы статическая переменная была инициализирована постоянным выражением, которое можно вычислить во время компиляции. При расчете констант могут использоваться адреса статических / глобальных переменных, где фактический адрес неизвестен до времени ссылки.
В этих случаях (например, char * char_p = & char_var или аналогичные) компилятор будет генерировать сборкуинструкции, чтобы отметить вычисленное значение для «перемещения» во время соединения. Перемещение, выраженное статической / глобальной переменной. Во время соединения компоновщик добавит фактический адрес статического / глобального к сохраненному значению.
Обратите внимание: char char_var = 'A' ; char *char_p = &char_var;
.file "b.c"
.text
.globl char_var
.data
.type char_var, @object
.size char_var, 1
# Char var initialized with a constant (65=A)
char_var:
.byte 65
.globl char_p
.section .data.rel.local,"aw",@progbits
.align 8
.type char_p, @object
.size char_p, 8
# Initialize char_p to global symbol, actual address resolved at link time.
char_p:
.quad char_var
.ident "GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0"
.section .note.GNU-stack,"",@progbits
Существует ограничение на возможность компоновщикарассчитать адрес во время ссылки. Он ограничен смещениями статического адреса +/-:
- & static_var
- & static_var + постоянная времени компиляции
- & static_var - постоянная времени компиляции
Но не '& static_var_1 - & static_var_2', что выдаст сообщение об ошибке, указывающее на ограничение: b.c:3:9: error: initializer element is not computable at load time
int v = &char_var - &char_v2 ;