Почему и когда использовать статические структуры в C-программировании? - PullRequest
34 голосов
/ 31 августа 2011

Я часто видел объявления статической структуры в коде драйвера, который меня попросили изменить.

Я пытался найти информацию о том, почему structs объявляется статическим и мотивация для этого.

Может кто-нибудь из вас, пожалуйста, помогите мне понять это?

Ответы [ 5 ]

31 голосов
/ 31 августа 2011

Ключевое слово static в C имеет несколько эффектов в зависимости от контекста, к которому оно применяется.

  • при применении к переменной, объявленной внутри функции, значение этой переменной будет сохраняться между вызовами функции.
  • при применении к переменной, объявленной вне функции, или к функции, видимость этой переменной или функции ограничивается "единицей перевода" , в которой она объявлена, то есть самим файлом. Для переменных это сводится к виду «локально видимой глобальной переменной».

Оба использования довольно распространены в относительно низкоуровневом коде, таком как драйверы.

Первый и последний применительно к переменным позволяют функциям сохранять понятие состояния между вызовами, что может быть очень полезно, но это также может вызвать всевозможные неприятные проблемы, когда код используется в любом контексте. где он используется одновременно, либо несколькими потоками, либо несколькими вызывающими. Если вы не можете гарантировать, что код будет строго вызываться последовательно одним «пользователем», вы можете передать своего рода «контекстную» структуру, которая поддерживается вызывающей стороной при каждом вызове.

Последнее, примененное к функциям, позволяет программисту сделать функцию невидимой извне модуля, и это МОЖЕТ быть несколько быстрее с некоторыми компиляторами для определенных архитектур, потому что компилятор знает, что это не так необходимо сделать переменную / функцию доступной за пределами модуля - например, чтобы функция была встроенной.

28 голосов
/ 03 сентября 2011

То, что, по-видимому, все остальные ответы, по-видимому, упускают: static есть и указывает также продолжительность хранения для объекта, наряду с , автоматическим (локальные переменные) и выделено (память возвращена malloc и друзьями).

Объекты со статической продолжительностью хранения инициализируются до запуска main (), либо с указанным инициализатором, либо, если он не был задан, как если бы ему был присвоен 0 (для структур и массивов это выполняется для каждого члена и рекурсивно) .

Вторым свойством static, установленным для идентификатора, является его связь , которая является концепцией, используемой во время соединения, и сообщает компоновщику, какие идентификаторы ссылаются на тот же объект. Ключевое слово static делает идентификатор внутренним связыванием 1017 *, что означает, что оно не может ссылаться на идентификаторы с тем же именем в другой единице перевода.

И чтобы быть педантичным ко всем небрежным ответам, которые я читал ранее: на статическую переменную нельзя ссылаться нигде в объявленном файле. Его область действия - только от объявления (которое может быть между определениями функций) до конца исходного файла - или даже меньше, до конца включающего блока.

9 голосов

struct переменная

Для структуры переменная как static struct S s;, это широко обсуждалось на: Что делает«статическое» среднее в C?

struct определение : без эффекта :

static struct S { int i; int j; };

точно так же, как:

struct S { int i; int j; };

, поэтому никогда не используйте его.GCC 4.8 выдает предупреждение, если вы делаете это.

Это потому, что определения структур не имеют хранения и не генерируют символы в объектных файлах, таких как переменные и функции.Просто попробуйте скомпилировать и декомпилировать:

struct S { int i; int j; };
int i;

с помощью:

gcc -c main.c
nm main.o

, и вы увидите, что нет символа S, но есть символ i.

Компилятор просто использует определения для вычисления смещения полей во время компиляции.

Это определения структуры, как правило, включаются в заголовки: они не будут генерировать несколько отдельных данных, даже если они включены несколько раз.

То же самое относится к enum.

C ++ struct определение : устарело в C ++ 11

C ++ 11 Стандартный эскиз N3337 Приложение C 7.1.1:

Изменение: В C ++ статические или внешние указатели могут применяться только к именам объектов или функций. Использование этихСпецификаторы с объявлениями типов недопустимы в C ++.В Си эти спецификаторы игнорируются при использовании в объявлениях типов.

См. Также: https://stackoverflow.com/a/31201984/895245

8 голосов
/ 31 августа 2011

Если вы объявите переменную как static, она будет видна только в этой единице перевода (если объявлено глобально) или сохранит свое значение от вызова к вызову (если объявлено внутри функции).

В вашем случае, я думаю, это первый случай. В этом случае, вероятно, программист не хотел, чтобы структура была видна из других файлов.

7 голосов
/ 31 августа 2011

Модификатор static для struct ограничивает область видимости структуры текущей единицей перевода (т. Е. Файлом).

ПРИМЕЧАНИЕ. В этом ответе предполагается (как указали другие респонденты), что ваше объявление не входит в функцию.

...