#c #misra
#c #мисра
Вопрос:
Как следует из названия, REDLIB определяет INT8_MIN как (-0x80). Это выдает предупреждения при использовании QAC для проверки совместимости с MISRA-C: (то же самое касается INT16 и INT32, которые равны -0x8000 и -0x80000000 соответственно)
Msg(4:1281) Integer literal constant is of an unsigned type but does not include a "U" suffix.
MISRA-C:2004 Rule 10.6; REFERENCE - ISO:C90-6.1.3.2 (Integer Constants)
Msg(4:3101) Unary '-' applied to an operand of type unsigned int or unsigned long gives an unsigned result.
MISRA-C:2004 Rule 12.9; REFERENCE - ISO:C90-6.3.3.3 Unary Arithmetic Operators - Semantics
Msg(4:2850) Constant: Implicit conversion to a signed integer type of insufficient size.
MISRA-C:2004 Rule 3.1; REFERENCE - ISO:C90-6.2.1.2 Conversions (to Signed Integers)
Комментарии:
1. Потому что другие значения были бы неправильными. Вы могли бы «исправить» предупреждение, сохранив правильное значение с помощью некоторого приведения. Но, по-видимому, разработчики redlib не беспокоятся о Misra.
2. @undur_gongor На самом деле нет никакого разумного способа «исцелить» что-либо здесь, не переписывая код.
-65536
вместо-0x8000
было бы совместимо с MISRA. Так было бы-(int16_t)0x8000
, хотя такая строка не имеет никакого смысла.3. @Lundin
(int16_t)0x8000
— это преобразование вне диапазона (вызывающее поведение, определяемое реализацией)
Ответ №1:
В стандарте C (C11 6.4.4.1) есть тонкое правило о целочисленных литералах («целочисленные константы»), в котором говорится, что если вы пишете простой целочисленный литерал, такой как 70000
без какого-либо суффикса U
или L
, тип литерала определяется следующим образом:
- Если литерал достаточно велик, чтобы его можно было сохранить в int, то он имеет тип int.
- В противном случае, если литерал достаточно велик для хранения в long , то он имеет тип long.
- (В противном случае в случае C99 / C11 литерал имеет тип long long).
Таким образом, 70000
в 16-разрядной системе тип long был бы.
Но когда вы пишете шестнадцатеричный целочисленный литерал (или восьмеричный), применяются другие правила. Вместо этого компилятор проверяет в этом порядке:
int
unsigned int
long int
unsigned long int
long long int
unsigned long long int
Итак, когда вы пишете 0x8000
в системе, где int равен 16 битам, компилятор проверяет: может ли он поместиться внутри int? Нет. Может ли он поместиться внутри unsigned int? ДА. Следовательно, тип 0x8000
является unsigned int и аналогично 0x80000000
имеет тип unsigned long.
Вот почему вы получаете ошибки MISRA для 0x8000
и 0x80000000
, потому что просто не имеет смысла применять унарный -
для неподписанного типа. Так что библиотека не соответствует MISRA-C.
Однако целочисленный литерал 0x80
всегда имеет тип int
в любой системе. Если вы получаете ошибку MISRA в этой строке, ваш инструмент статического анализа не работает для этого правила. Отправьте отчет об ошибке в PRQA.
Комментарии:
1. Наш текущий процессор — 32-разрядная версия ARM NXP, поэтому наш базовый тип всегда равен 32 битам, а не 16 битам,?
2. @Daantimmerесли INT16 определено как
-0x8000
, вы либо используете 16-разрядный компилятор, либо ваш компилятор действительно странный. Здравомыслящие компиляторы определяют short как 16 бит, а int — как ширину шины данных для данного процессора. Но, конечно, C также допускает безумные реализации. Я бы посоветовал использовать нормальный компилятор…3.Используемый компилятор — это arm-none-eabi-gcc от GCC, поставляемый с LPCXpresso от NXP.
stdint.h
определяет:#define INT8_MIN (-0x80)
#define INT16_MIN (-0x8000)
#define INT32_MIN (-0x80000000)
и typedefs как:typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;
Я думаю, это вполне вменяемый компилятор 🙂4. @Daantimmerмм, я, наверное, просто перепутал INT16_MIN с INT_MIN. Тем не менее, это делает оба
0x80
и0x8000
int, и анализатор не должен жаловаться на них.5. @DaanTimmer
-0x80000000
просто неправильно там. Отправьте отчет об ошибке! Это должно быть(-0x7FFFFFFF - 1)
или эквивалентно. Другие определения в порядке. Кстати, отредактируйте эту информацию в своем вопросе.