Ошибка 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},
};