Я нахожу стиль кодирования в STM32F0 (микроконтроллер ARM Cortex-M0) SPL (стандартная периферийная библиотека) излишне многословным. В качестве примера, вот фрагмент кода для настройки контура фазовой автоподстройки частоты для SYSCLK:
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
Где RCC_CFGR_SW
и RCC_CFGR_SW_PLL
макросы для целочисленных литералов уже приведены к uint32_t
.
#define RCC_CFGR_SW ((uint32_t)0x00000003)
#define RCC_CFGR_SW_PLL ((uint32_t)0x00000002)
И RCC->CFGR
является (отображенным в память) экземпляром структуры типа
typedef struct
{
...
__IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x04 */
...
} RCC_TypeDef;
Таким образом, результат будет неявно приведен в uint32_t
любом случае, даже с предупреждением, если произойдет что-то смешное (в отличие от того, что произойдет с явным приведением).
Можно ли исключить эти явные приведения, особенно учитывая, что C99 гарантирует (6.3.1.3), что
Позволяет упростить код до значительно более ясного
//Select the PLL as system clock source
RCC->CFGR &= ~(RCC_CFGR_SW);
RCC->CFGR |= RCC_CFGR_SW_PLL;
Или это может вызвать непредвиденные побочные эффекты? Я не совсем уверен, и я предполагаю, что люди, которые написали этот код, более опытны в написании встроенного C, чем я...
Я задаю этот вопрос на electronics.stackexchange вместо stackoverflow, поскольку он довольно специфичен для встроенного программирования низкого уровня.
Давненько я не тратил время на чтение стандартов C. Но есть ключ из всего того, что может быть полезно, в общем. Я не думаю, что это большая помощь здесь, хотя. Позвольте мне изложить то, что я помню, а затем рассмотреть, есть ли какие-либо дополнительные комментарии. (Однако я не уверен, что здесь стоит искать авторов компиляторов C, и именно они должны знать точные детали.)
Когда C преобразует целое число со знаком в целое число без знака того же физического размера, стандарт требует , чтобы компилятор C выдавал результат без знака, который либо (1) имел бы то же самое эквивалентное значение, означающее в пространстве символов без знака, либо иначе; (2) значение со знаком по модулю . Такие преобразования гарантируют конкретный математический результат. Тот, который большинство людей ожидает, на самом деле. Однако, когда беззнаковое целое число преобразуется в знаковое целое, опять же того же физического размера, стандарт требует , чтобы , если и только если существует эквивалентное значение, означающее , то это значение должно поддерживаться. Если, однако, беззнаковое значение превышает предел положительного значения, означающего , то стандартного результата вообще не будет. Я полагаю, что компилятор C может генерировать случайную чепуху, если захочет.
Возможно, левая рука не знает, что делает правая в кодировании, которое вы видите. Вы, конечно, можете пойти посмотреть и увидеть очевидное. Но возможно, что те, кто пишет выражения, пытаются защищаться в том смысле, что кто-то может позже переписать константу из того, что раньше было беззнаковым значением, в значение со знаком (или по умолчанию со знаком). (Компиляторам C разрешено или раньше разрешалось делать свой собственный выбор по умолчанию, когда спецификатор signed или unsigned отсутствовал. И если им не разрешалось, некоторые, безусловно, все равно это делали.)
Приведение объектов к неподписанным всегда гарантирует конкретный результат. Так безопаснее использовать. Или когда-то был, когда я читал стандарты много лет назад. На всякий случай кто-то использовал явно или по умолчанию компилятора значение со знаком.
Все это говорит о том, что я не могу вспомнить компилятор C, который делал бы что-то сумасшедшее при преобразовании целого числа без знака в целое число со знаком. В общем, если предположить, что компьютерное оборудование использует обычную запись с дополнением до двух, все они просто делают очевидное и делают их побитово идентичными. Позже меняется только интерпретация. Но это не значит, что кого-то, кто действительно читал стандарты, это должно волновать — они могут решить написать так, как будто существует сумасшедший компилятор C. Просто чтобы доказать, что они читали стандарт.
Теперь я не рассматривал код, который вы показываете, в контексте экземпляров разного размера. Но вышеизложенное может дать вам представление о том, почему вы видите там такие вещи.
ПлазмаHH
Армандас
трубка
Арсенал
Роберт Бристоу-Джонсон
RCC->CFGR
такжеuint32_t
, то приведения в первых двух утверждениях полностью избыточны. вокруг много паршивых программистов, которые не понимают, что помимо написания работающего кода важно также сделать его кратким, читабельным и простым в сопровождении.пользователь207421
Питер Смит