Статические изменчивые, статические пустоты и статические различия в коде C
Я работал над тем, чтобы понять библиотеку twi для микроконтроллеров AVR и, глядя в файл.h, есть следующие переменные со статическим спецификатором.
Итак, все переменные в этой библиотеке имеют префикс static, а некоторые объединяются с volatile и void, а одна - только static.
Итак, какова роль каждой комбинации для этой конкретной библиотеки? Я имею в виду, как это повлияет на общее поведение кода.
Вот переменные, которые я нашел в twi.c, я узнал здесь, что вы можете объявлять и определять переменные только в файле.c, не объявляя их в файле.h. А также вы можете инициализировать или деинициализировать их в.c файле. Это мое предположение верно?
static volatile uint8_t twi_state;
static volatile uint8_t twi_slarw;
static volatile uint8_t twi_sendStop; // should the transaction end with a stop
static volatile uint8_t twi_inRepStart; // in the middle of a repeated start
static void (*twi_onSlaveTransmit)(void);
static void (*twi_onSlaveReceive)(uint8_t*, int);
static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
static volatile uint8_t twi_masterBufferIndex;
static volatile uint8_t twi_masterBufferLength;
static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
static volatile uint8_t twi_txBufferIndex;
static volatile uint8_t twi_txBufferLength;
static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];
static volatile uint8_t twi_rxBufferIndex;
static volatile uint8_t twi_error;
С Уважением,
4 ответа
Статический - в этом случае переменная видна только внутри текущего файла
volatile - это информация для компилятора о том, что объект может быть изменен чем-то вне обычного пути выполнения (например, подпрограмма прерывания), и гарантирует, что переменная будет прочитана перед любым использованием и записана после каждого изменения. volatile (что является очень распространенным недоразумением) не гарантирует ничего другого - ни атомарности, ни когерентности кэша и т. д. и т. д.
Здесь было дано много хороших ответов, но не упоминалось о масштабах.
Статические переменные после инициализации и последующего изменения в области видимости сохраняют изменения и никогда не уничтожаются и не инициализируются снова, особенно при выходе из области видимости. Нет, если только это не продиктовано кодом. Можно сказать, что статические переменные напоминают глобальные переменные с точки зрения их жизненного цикла, но доступ к ним возможен только в пределах их собственной области видимости.
Нестабильная часть имеет тенденцию принудительно вызывать выполнение переменной из ОЗУ, а не кэшированной копии в регистрах или флэш-памяти. Предположим, например, что определенный код был отправлен компилятору с определенным уровнем настройки оптимизации. Компилятор не предполагает, что к переменным присоединены какие-либо дополнительные условия, кроме их очистки, когда они не используются или выходят за пределы их области действия. По своей сути volatile имеет двойное применение: либо игнорировать оптимизацию, предлагаемую компилятором для этой переменной, либо воздерживаться от использования предварительно выбранной копии этой переменной, кроме той, что находится в ОЗУ.
Статическая изменчивость — это комбинация обоих поведений, сохранение этой переменной в оперативной памяти без какой-либо оптимизации.
Возможные области применения:
- Программирование флэш-памяти
- Циклические буферы
- Кольцевые буферы
- Параллелизм и многопроцессорность/многопоточность
static: статическая переменная относится к переменной класса, которая используется всеми экземплярами.
volatile: изменчивые переменные - это те, которые читаются и записываются в основную память. Они не хранятся в локальном кеше, всегда извлекаются из основной памяти. Например, если два потока используют, скажем, private volatile int x; если поток A пишет (x) и поток B читает (x), то одновременно и запись, и чтение из основной памяти без использования локального кеша потоков.
static volatile: даже если статические переменные являются общими переменными, но в другом потоке может быть другое значение для статической переменной в локальном кеше потока. Чтобы сделать его согласованным для всех потоков, просто объявите его как static volatile. Поэтому каждый раз он будет извлекаться из основной памяти.
Для ключевых слов static
а также volatile
там написано достаточно...
Смотрите, например:
Что касается интерфейса TWI, voltatile
необходим, потому что функции, которые изменяют эти переменные, могут вызываться из разных обработчиков прерываний. Если volatile
будет удален, компилятор будет оптимизировать код, не зная, что код может быть прерван. Это может привести к сбоям.