EDIT:
Лундин указал в комментариях, что MISRA C: 2012 еще не поддерживает C11 с 2018 года, поэтому следующий ответ, к сожалению, не удовлетворит соответствие MISRA без отклонения.
Оригинал
C11 приносит с собой _Generic
, который позволяет вам иметь макросы, которые выполняют различные действия в зависимости от типа, переданного в него. Как пример с вашим POWER_OF_TWO, вы можете сделать что-то вроде этого:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define POWER_OF_TWO(X) _Generic((X), \
uint8_t: ((X) != 0u) && (!((X)&((X) - 1u))), \
int8_t: ((X) > 0) && (!((X)&((X) - 1))) \
)
int main( void ){
uint8_t a = 2;
int8_t b = 2;
printf("%d\n", POWER_OF_TWO(a));
printf("%d\n", POWER_OF_TWO(b));
a++;
b++;
printf("%d\n", POWER_OF_TWO(a));
printf("%d\n", POWER_OF_TWO(b));
}
Или, учитывая предложения Дуга Керри и Лундина по использованию встроенных функций, которые безопасны для префикса / постфикса:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
static inline _Bool power_of_two_int8(int8_t x) {
return (x > 0) && (!(x & (x - 1)));
}
static inline _Bool power_of_two_uint8(uint8_t x) {
return (x != 0u) && (!(x&(x - 1u)));
}
#define POWER_OF_TWO(X) _Generic((X), \
uint8_t: power_of_two_uint8((X)), \
int8_t: power_of_two_int8((X)) \
)
int main( void ){
uint8_t a = 2;
int8_t b = 2;
printf("%d\n", POWER_OF_TWO(a++));
printf("%d\n", POWER_OF_TWO(b++));
printf("%d\n", POWER_OF_TWO(a));
printf("%d\n", POWER_OF_TWO(b));
return EXIT_SUCCESS;
}
Подробнее о _Generic
можно узнать на CppReference или в разделе 6.5.1.1 черновика стандарта C11.