Чтобы ответить на вопрос в заголовке, имея в виду пример кода, да, может.Стандарт C говорит столько же в §6.2.4 :
Время жизни объекта - это часть выполнения программы, в течение которой гарантируется хранениебыть зарезервированным для этого.Объект существует, имеет постоянный адрес и сохраняет свое последнее сохраненное значение в течение всего времени его жизни.
Для такого объекта, у которого нет типа массива переменной длины, его время жизни простирается от входа в блок, с которымон ассоциируется до тех пор, пока выполнение этого блока не закончится каким-либо образом.
Так что да, вы можете взять адрес переменной из точки объявления, потому что объект имеет адрес в этой точке, и этов рамках.Ниже приводится сжатый пример этого:
void *p = &p;
Это служит очень малой цели, но совершенно справедливо.
Что касается вашего второго вопроса, что вы можете с ним сделать.В основном я могу сказать, что не буду использовать этот адрес для доступа к объекту до завершения инициализации, потому что порядок вычисления выражений в инициализаторах не указан ( §6.7.9 ),Вы можете легко найти свою ногу отстрелянной.
Единственное место, где это происходит, - это определение всех видов табличных структур данных, которые должны быть самоссылочными.Например:
typedef struct tab_row {
// Useful data
struct tab_row *p_next;
} row;
row table[3] = {
[1] = { /*Data 1*/, &table[0] },
[2] = { /*Data 2*/, &table[1] },
[0] = { /*Data 0*/, &table[2] },
};