#c #embedded #misra
#c #встроенный #misra
Вопрос:
При проверке некоторого кода с помощью Misra он сгенерировал следующие сообщения
Unpermitted operand to operator '>>' [MISRA 2012 Rule 10.1 required]
Unpermitted operand to operator 'amp;' [MISRA 2012 Rule 10.1 required]
Я не смог разобраться в проблеме, а описание правила 10.1 очень общее и не очень помогает. Соответствующий фрагмент кода приведен ниже.
float variable2;
variable2= 814.00f;
Data[0] = (((Int16) variable2) >> 8) amp; ((Int16)0xFF);
Data[1] = ((Int16) variable2) amp; ((Int16)0xFF);
В чем проблема с использованием операторов в этом коде?
Комментарии:
1. Может быть, потому, что
Int16
это знаковый тип?2. Я задавался этим вопросом, но это также для
amp;
. Возможно, MISRA не нравится потеря значимости, хотя приведение обычно скрывает это.
Ответ №1:
Вы никогда не должны использовать целые числа со знаком в побитовой арифметике. С этим связано много плохо определенного поведения. Сдвиг влево на отрицательное значение приводит к неопределенному поведению. Сдвиг вправо на отрицательное значение приводит к определяемому реализацией поведению (либо арифметическому, либо логическому сдвигу).
Поэтому в MISRA-C есть требование, чтобы все такие переменные имели то, что они называют по существу беззнаковым типом.
Кроме того, использование 16-разрядного типа независимо от наличия подписи небезопасно в 32-разрядной системе, потому что они будут неявно переведены в 32-разрядный подписанный int
. Я предположу, что вы используете 32-разрядную систему, иначе использование чисел с плавающей запятой, вероятно, вообще не имеет смысла.
В вашем случае вы не можете перейти непосредственно от float к unsigned, так как вы потеряли бы знаковый бит. Это означает, что сначала вам нужно сделать один шаг к подписанному типу.
float f32 = 814.00f;
int32_t s32 = (int32_t)f32;
uint32_t u32 = (uint32_t)s32;
Data[0] = ((u32 >> 8) amp; 0xFFu);
Data[1] = (u32 amp; 0xFFu);
Это должно быть совместимо с MISRA-C, хотя это также зависит от типа Data
.
u
суффикса для целочисленных констант достаточно, вам не нужно их приводить.- Используйте типы stdint.h, а не какие-то самодельные типы.
- Дополнительная скобка вокруг операндов
amp;
требуется для рекомендательного MISRA-C: 2012 12.1. Ваш код не соответствовал этому правилу, приведенный выше код соответствует.