Вы можете инициализировать указатель в глобальной области видимости для любого значения, которое является либо константным выражением, либо разрешается компоновщиком.Это потому, что компилятор C помещает константы прямо в код инициализации.Ссылочные символы также помещаются в код инициализации, и компоновщик заменяет эти символы действительными значениями адреса.
// global scope
int foo;
int* bar = &foo; // ok, since &foo is a known address
int* bar2 = &foo+1; /* ok, since &foo is a known
address and the offset is constant. */
int* whatever = (int*) 0xabcd; /* Ok, since 0xabcd is
a constant value, and can be used as
an address, but it depends on your
environment if this address makes any
sense */
int *baz = bar; /* not OK, since the value of bar is
stored into the RAM at run time,
and the linker can't determine that
this value does point to &foo */
В функции вы можете инициализировать любую нестатическую переменную-указатель значением, которое уже существует,Это потому, что эти инициализации работают как обычные присвоения переменных.
Редактировать: Недопустимая int *baz = bar;
часть
Отказ от ответственности: я описываю поведение типичного компилятора +наборы инструментов компоновщика, встречающиеся в Windows, Linux и * BSD, во встроенном мире инициализация может выглядеть очень по-разному.
Все инициализации переменных на глобальном уровне помещаются в отдельный сегмент данных в исполняемом файлеи копируются при запуске программы в ОЗУ.Это означает, что компоновщик должен создавать эти разделы путем сбора всех глобальных переменных и разрешения ссылок на символы в этом разделе.Компоновщик может разрешать только те значения, которые содержат только значения констант времени соединения, которые являются адресами и числовыми константами.Оператор int *baz = bar;
использует косвенное значение, bar
.Хотя bar может быть разрешена до &foo
в данном конкретном случае, компилятору это не важно, поскольку стандарт требует, чтобы это было присваивание baz
с содержимым оперативной памяти bar.И поскольку такие ссылки на память во время выполнения недоступны для компоновщика, так как компоновщик не может запустить программу, компилятор отказывается генерировать код для этого оператора.
Также изменяется тип bar
с int* bar
to int* const bar
не помогает, потому что также константа имеет область памяти, и компилятор C должен действовать так, как будто он использует эту область памяти, когда значения используются где-то.Это означает, что даже когда ясно, какое значение имеет bar
, компилятор не может поместить постоянное значение в объектный код, поскольку стандарт требует, чтобы память времени выполнения использовалась для определения значения bar
, когда оноused.
В качестве примечания, в C ++ разрешено делать инициализации, основанные на данных времени выполнения.