Откуда берется имя локальной статической переменной? Это идентификатор процесса или случайное число?
В gcc langhooks.c стандартная реализация ловушки set_decl_assembler_name
(которая используется непосредственно для языка C) содержит :
/* By default, assume the name to use in assembly code is the same
as that used in the source language. (That's correct for C, and
GCC used to set DECL_ASSEMBLER_NAME to the same value as
DECL_NAME in build_decl, so this choice provides backwards
compatibility with existing front-ends. This assumption is wrapped
in a target hook, to allow for target-specific modification of the
identifier.
Can't use just the variable's own name for a variable whose scope
is less than the whole compilation. Concatenate a distinguishing
number - we use the DECL_UID. */
if (TREE_PUBLIC (decl) || DECL_FILE_SCOPE_P (decl))
id = targetm.mangle_decl_assembler_name (decl, DECL_NAME (decl));
else
{
const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
char *label;
ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
id = get_identifier (label);
}
И комментарий к макросу DECL_UID
говорит:
/* Every ..._DECL node gets a unique number. */
Таким образом, число - это некоторый идентификатор, придуманный gcc, который гарантированно будет отличаться для каждого объявления, видимого в модуле перевода (включая объявления в #include
-d файлах). Этого достаточно, чтобы убедиться, что если разные области используют локальные статические переменные с одинаковыми именами, они будут иметь разные искаженные имена символов в сборке и объектном коде.
Означает ли то, что в global_static
нет недопустимых символов, подразумевается, что я мог бы сделать extern static int global_static;
в другом файле и прочитать global_static
?
Нет. С одной стороны, нельзя объединять extern
и static
, поскольку они дают конфликтующие связи с переменной. Обратите внимание, что static
имеет два совершенно разных значения в C: внутри функции это означает, что переменная имеет статическую продолжительность хранения. Вне функции это означает, что переменная или функция имеет внутреннюю связь. (Переменная, которая не является локальной для функции, всегда имеет статическую продолжительность хранения.)
Таким образом, с точки зрения языка C, static
on global_static
означает, что переменная имеет внутреннюю связь, что означает, что она никогда не должна рассматриваться как та же самая переменная, что и любая другая единица перевода, поэтому существует нет способа получить к нему прямой доступ из другого * .c файла. При переводе в объекты ELF или другие распространенные форматы объектов это делается путем превращения символа для переменной в «локальный» символ вместо «глобального» символа. При связывании исполняемых файлов или загрузке динамических библиотек глобальный символ может удовлетворять неопределенному символу из другого объекта, но локальный символ никогда не удовлетворяет.
Обратите внимание, что инструмент nm
печатает заглавные буквы типа символов для глобальных символов и строчные буквы типа символов для локальных символов, поэтому d
рядом с переменными в выходных данных означает, что оба являются локальными символами и не могут использоваться напрямую другими объектами.