Ошибка MISRA-C в инициализации массива структуры

У меня есть следующее:

typedef struct
{
   uint8_t BlockID;
   uint32_t Copies;
   uint16_t Size;
}NVMM_ConfigType;

const NVMM_ConfigType NvmmCnf_Layout[6] =
{
   {  1, 1,   4},
   {  2, 3,   4},
   {  5, 5,  16},
   { 10, 1,   4},
   { 11, 2,  32},
   { 13, 1, 100},
};

Что мне кажется нормальным, но MISRA-C выдает следующую ошибку:

MISRA C: 2012 нарушение правила 10.3: [R] Значение выражения не должно присваиваться объекту с более узким существенным типом или другой категории существенного типа

Я пытался выяснить, почему это происходит, но я просто вижу это. Кроме того, результаты сборки страдают от этих ошибок в подобных ситуациях, и я не знаю, почему.

Кто-нибудь знает, что происходит?

РЕДАКТИРОВАТЬ: Я также попытался явно привести каждое значение и все еще получаю ту же ошибку:

const NVMM_ConfigType NvmmCnf_Layout[6] =
{
    {  (uint8_t)1, (uint32_t)1,   (uint16_t)4},
    {  (uint8_t)2, (uint32_t)3,   (uint16_t)4},
    {  (uint8_t)5, (uint32_t)5,  (uint16_t)16},
    { (uint8_t)10, (uint32_t)1,   (uint16_t)4},
    { (uint8_t)11, (uint32_t)2,  (uint16_t)32},
    { (uint8_t)13, (uint32_t)1, (uint16_t)100},
};

3 ответа

(Привет, это новый аккаунт, поэтому я пока не могу использовать раздел комментариев, чтобы попросить дальнейших разъяснений, поэтому извините за длинный ответ)

Чтобы быть конкретным, это Правило 10.3 относится к MISRA-C:2012 (последний стандарт), который является значительным улучшением по сравнению с предыдущими версиями, поскольку существует больше усилий по объяснению обоснования MISRA, а также много более совместимых и несовместимых примеров.

Обоснование правила таково: поскольку C позволяет автоматически выполнять присваивания между различными арифметическими типами, использование этих неявных преобразований может привести к непредвиденным результатам с возможностью потери значения, знака или точности. MISRA_C:2012 имеет существенную модель типов, которая поможет предупредить, когда это может произойти.

Описания правил также включают исключения из правил. Для правила 10.3 одно исключение: неотрицательное целочисленное константное выражение по существу со знаком типа может быть назначено объекту по существу без знака типа, если его значение может быть представлено в этом типе.

Непонятно, по какой именно строке и столбцу ваш инструмент сообщает о нарушении (должно). Лучшие из инструментов также предоставят более подробную информацию о том, какая именно часть правила нарушается (например, если вместо 1 у вас было 128 в первом присваивании 8-битному, инструмент должен быть очень четко об этом).

В любом случае, я (и мой инструмент) не вижу здесь никакого нарушения 10.3.

Поскольку это "разрешимое" правило, я бы поинтересовался инструментом, если это критичный для безопасности код, помимо того, что он тратит ваше время.

Большинство инструментов позволяют вам подавить предупреждение и задокументировать причину (в данном случае это ошибка в инструменте).

Если вашему поставщику инструмента требуется дополнительная информация, вы можете опубликовать свой вопрос на дискуссионном форуме по адресу http://www.misra-c.com/ чтобы получить официальный ответ и направить его поставщику.

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

Я предполагаю, что вы должны привести каждое значение в инициализаторе к типу соответствующего поля. Но, как указано в правиле, это все равно будет нарушением.

Когда я использую PC-Lint для проверки правил Misra, мне часто приходится добавлять u суффикс к константам:

const NVMM_ConfigType NvmmCnf_Layout[6] =
{
   {  1u, 1u,   4u},
   {  2u, 3u,   4u},
   {  5u, 5u,  16u},
   { 10u, 1u,   4u},
   { 11u, 2u,  32u},
   { 13u, 1u, 100u},
};

Это устраняет int в unsigned преобразование.

Если этого не достаточно, тогда бросает:

const NVMM_ConfigType NvmmCnf_Layout[6] =
{
   { (uint8_t ) 1u, 1u, (uint16_t )  4u},
   { (uint8_t ) 2u, 3u, (uint16_t )  4u},
   { (uint8_t ) 5u, 5u, (uint16_t ) 16u},
   { (uint8_t )10u, 1u, (uint16_t )  4u},
   { (uint8_t )11u, 2u, (uint16_t ) 32u},
   { (uint8_t )13u, 1u, (uint16_t )100u},
};
Другие вопросы по тегам