Правильный ответ: «это зависит».
(printf должен использовать директиву "% p" и преобразовать адрес в "void *", для ясности:
printf("%p\n", (void *)&a);
хотя использование% u без сомнения работает для вашего конкретного компилятора с любыми используемыми вами флагами.)
Как отметил @Alex, адрес является виртуальным, если происходит трансляция (как в большинстве современных ОС или даже при работе в «эмулированной физической» под виртуальной машиной). Сам адрес обычно определяется во время ссылки или загрузки, если «a» имеет статическую продолжительность хранения, но во время выполнения (в стеке, как сказал @Als), если нет. Переменные, объявленные как «статические» или «внешние», имеют статическую длительность; переменные, объявленные вне тел функций, имеют статическую длительность; и переменные, объявленные внутри тел функций, но без использования «extern» или «static», имеют автоматическую продолжительность хранения (и, таким образом, обычно находятся в «стеке» - хотя может быть более одного стека, как при использовании потоков POSIX).