2016-11-02 12 views
2

В огромном макро у меня есть в программе, направленной на 16-битный процессор, следующий код (упрощенно) появляется несколько раз:MISRA предупреждения 12.4: целое преобразование в результате усечения (операция отрицания)

typedef unsigned short int uint16_t; 
uint16_t var; 
var = ~0xFFFF; 

MISRA жалуется на предупреждение 12.4: целочисленное преобразование приводит к усечению. Инструментом, используемым для этого, является Coverity.

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

Я пробовал много вещей, и вот последняя попытка, которая терпит неудачу также:

var = (uint16_t)((~(uint16_t)(0xFFFFu))&(uint16_t)0xFFFFu); 

(значение 0xFFFF это просто пример В настоящем коде значение переменной, которая может принимать любое значение. (но 16 бит))

Есть ли у вас какие-либо другие идеи, пожалуйста? Благодарю.

EDIT:

Я попытался затем использовать значение 32бит и результат тот же со следующим кодом:

typedef unsigned int uint32_t; 
uint32_t var; 
var = (uint32_t)(~(uint32_t)(0xFFFF0000u)); 
+0

вы можете просто использовать 'вар = 0;' – user3528438

+0

В реальном коде, делать у вас действительно есть '~ 0xffff'? Вы знаете, что '~ 0xffff' равно' 0'? –

+0

Спасибо, ребята, но значение 0xFFFF - всего лишь пример. В фактическом коде значение представляет собой переменную, которая может принимать любое значение (но 16 бит). – Ben9000RPM

ответ

0

Когда компилятор смотрит на правой стороне, первый он видит буквальное 0xFFFF. Он автоматически повышается до целого числа, которое (очевидно, из предупреждения) 32-бит в вашей системе. Теперь мы можем представить это значение как 0x0000FFFF (всего 32-битного). Когда компилятор выполняет операцию ~ на нем, он становится 0xFFFF0000 (целым 32-битным). Когда вы пишете var = ~0xFFFF;, компилятор фактически видит var = 0xFFFF0000; непосредственно перед назначением операции. И, конечно, усечение происходит во время этого задания ...

+1

Моя система - 16 бит. Но, возможно, Coverity не видит этого и расширяет его до 32 бит, я не знаю. – Ben9000RPM

+0

Я попытался с uint32_t, и предупреждение все еще присутствует ... – Ben9000RPM

+1

@ Ben9000RPM: Ваш первый комментарий имеет смысл, но второй предлагает что-то неправильное (возможно, проблема конфигурации) с анализатором ... – Malkocoglu

2

Резюме:

Предполагая, что вы используете статический анализатор для MISRA-C: 2012, вы должны были получить предупреждение о нарушениях в отношении правила 10.3 и 7.2.

Правило 12.4 касается только обертки беззнаковых целочисленных констант, которые могут встречаться только с бинарными + и - операторами. Здесь это не имеет значения.


Текст предупреждения, кажется, не имеет смысла ни для MISRA-C: 2004 12.4 ни MISRA-C: 2012 12.4. Возможно, инструмент отображает неправильное предупреждение.

Существует, однако, правило 10.3 MISRA: 2012, которое запрещает присваивать значение переменной меньшего размера, чем предполагалось в выражении.

Чтобы использовать термины Мишра, то существенного типа из ~0xFFFF беззнаковых, так как шестигранная литерал типа unsigned int. В вашей системе unsigned int, по-видимому, больше, чем uint16_t (int - это «более ранжированный» целочисленный тип, чем короткий в стандарте 6.3.1.1, даже если они имеют одинаковый размер). То есть, uint16_t имеет более узкий существенный тип, чем unsigned int, поэтому ваш код не соответствует правилу 10.3. Это то, что должен был сообщить ваш инструмент.

Настоящая техническая проблема, которая скрыта за терминами MISRA, заключается в том, что оператор ~ опасен, поскольку он поставляется с неявным целым продвижением. Что, в свою очередь, вызывает код, как, например

uint8_t x=0xFF; 
~x << n; // BAD, always a bug 

вызвать неопределенное поведение, когда значение 0xFFFFFF00 остается сдвинуты.

Поэтому всегда полезно направить результат оператора ~ на правильный, предназначенный тип. Было даже явное правило об этом в MISRA 2004, которое теперь слилось с правилами «основного типа».

Кроме того, MISRA (7.2) утверждает, что все целочисленные константы должны иметь суффикс u или U.

MISRA-C: 2012 совместимый код будет выглядеть следующим образом:

uint16_t var; 
var = (uint16_t)~0xFFFFu; 

или слишком педантичным:

var = (uint16_t)~(uint16_t)0xFFFFu; 
+0

Спасибо за эту разработку. К сожалению, var = (uint16_t) ~ (uint16_t) 0xFFFFu; все еще вызывает предупреждение. Более того, я не получаю никаких других предупреждений, чем 12.4. – Ben9000RPM

+0

Я попытался использовать значение 32 бит, и результат будет таким же, как в следующем коде: typedef unsigned int uint32_t; uint32_t var; var = (uint32_t) (~ (uint32_t) (0xFFFF0000u)); – Ben9000RPM

+1

@ Ben9000RPM Кажется, ошибка инструмента. Что неудивительно, 95% всех шашек MISRA на рынке нарушены без ремонта.Не обфускайте свой код, просто напишите 'var = (uint16_t) ~ 0xFFFFu;' который абсолютно безопасен и игнорирует инструмент. – Lundin