MISRA C: 2004: вместо основных типов следует использовать typedef, которые указывают размер и подпись.

У меня есть это нарушение MISRA C:2004 typedefs that indicate size and signedness should be used in place of the basic types

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

static int handlerCalled = 0;

int llvm_test_diagnostic_handler(void) {
  LLVMContextRef C = LLVMGetGlobalContext();
  LLVMContextSetDiagnosticHandler(C, &diagnosticHandler, &handlerCalled);

person Gianni Spear    schedule 04.02.2019    source источник
comment
он, вероятно, хочет, чтобы вы использовали типы stdint.h, такие как int32_t, если вам нужен 32-битный подписанный int, а не int.   -  person Christian Gibbons    schedule 04.02.2019
comment
ОП: это строка, на которую жалуется ваша MISRA-checker, та, что инициализирует handlerCalled : static int handerCalled = 0; ? Если это так, я совершенно уверен, что @ChristianGibbons прав в своем предположении.   -  person Morten Jensen    schedule 04.02.2019
comment
Спасибо, я попытался добавить #include ‹stdint.h›; определение типа int uint32_t; а я исправил с помощью статического uint32_t handlerCalled = 0; uint32_t llvm_test_diagnostic_handler(void) и теперь работает!   -  person Gianni Spear    schedule 04.02.2019
comment
Не совсем так, @GianniSpear. Вы должны #include <stdint.h>, но не должны писать собственное typedef для uint32_t. Используйте определения типов, представленные в заголовке, так как вы можете положиться на них, чтобы быть правильными для вашей конкретной системы.   -  person John Bollinger    schedule 04.02.2019
comment
Спасибо @JohnBollinger. Я не получил вашей помощи. Не могли бы вы сделать простой пример, пожалуйста? (Я очень новичок в правилах MISRA-C). заранее спасибо   -  person Gianni Spear    schedule 04.02.2019
comment
uint32_t предназначен для 32-битных чисел без знака, и поэтому никогда не должен быть преобразован в тип int, который является знаковым. Такие ошибки являются одной из причин, по которой, как настоятельно советовал @JohnBollinger, вам не следует самостоятельно выполнять определения типов. stdint.h уже делает за вас все определения типов. Просто включите заголовок и используйте типы, которые он определяет.   -  person Christian Gibbons    schedule 04.02.2019
comment
Лучший вариант — использовать MISRA-C:2012 и C99 (или новее), если вы не застряли на более старой цепочке инструментов. Решает кучу проблем - это было бы не проблемой.   -  person Lundin    schedule 05.02.2019


Ответы (1)


Правило MISRA нацелено на то, что C не определяет точный размер, диапазон или представление своих стандартных целочисленных типов. Заголовок stdint.h смягчает эту проблему, предоставляя несколько семейств определений типов выражающие целочисленные типы, поддерживаемые реализацией, которые обеспечивают определенные комбинации подписи, размера и представления. Каждая реализация C предоставляет заголовок stdint.h, соответствующий этой реализации.

Вы должны соблюдать правило MISRA, используя типы, определенные в заголовке stdint.h вашей реализации, выбирая типы, отвечающие вашим потребностям, среди тех, которые он действительно поддерживает (или тех, которые, как вы ожидаете, будут поддерживаться). Например, если вам нужен целочисленный тип со знаком шириной ровно 32 бита, без дополнительных битов и выраженный в виде дополнения до двух, то это будет int32_t -- если ваша реализация вообще это обеспечивает (было бы удивительно, но не невозможно, чтобы такой тип был недоступен).

Например,

#include <stdint.h>

// relies on the 'int32_t' definition from the above header:
static int32_t handlerCalled = 0;

Вопрос, который я поднимал в своем комментарии, заключался в том, что вы, кажется, сказали, что не только включили заголовок, но и определили свой собственный typedef для uint32_t. Вы не должны определять собственное определение типа для этого или других типов в области stdint.h. В лучшем случае это избыточно, но в худшем случае это удовлетворяет требованиям программы проверки MISRA, но ломает ваш код.

person John Bollinger    schedule 04.02.2019
comment
MISRA-C:2004 поддерживает только C90. stdint.h скорее всего недоступен. Тогда правильный курс действий — написать некоторые вещи препроцессора, проверяющие #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L #include <stdint.h> #else typedef .... По этой причине MISRA-C:2004 не говорит, какие типы следует использовать вместо типов по умолчанию. В текущей директиве 4.6 MISRA-C:2012 явно рекомендуется использовать stdint.h. - person Lundin; 05.02.2019