Соответствующий Misra макрос для Power of 2 in C - PullRequest
0 голосов
/ 02 июля 2018

У меня есть следующий макрос

#define POWER_OF_TW0(x) ( ((x) > 0)  && (!((x)&((x) - 1))))

Чтобы сделать его совместимым с misra, я попробовал

#define POWER_OF_TW0(x) ( ((x) > 0)  && (!((unsigned)(x)&((unsigned)(x) - 1u))))

Но это все еще не соответствует норме, потому что, если код такой, как показано ниже

uint8_t val = 4;
if(POWER_OF_TWO(val))
{
   ..
}

Инструмент misra будет жаловаться на число без знака по сравнению с номером со знаком 0 ((x) > 0).

будет рад, если декларация для val была подписана, например int8_t.

Я чувствую, что единственный выход - рассмотреть этот макрос, которому будут даны положительные числа, и изменить код на ((x) != 0u) т.е.;

#define POWER_OF_TW0(x) ( ((x) != 0u)  && (!((unsigned)(x)&((unsigned)(x) - 1u))))

Пожалуйста, дайте мне знать, если есть альтернативное решение.

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

Используйте статическую встроенную функцию вместо макроса. (В любом случае MISRA советует не использовать «макрофункции», см. этот вопрос SO , так что вы должны сделать это в любом случае.) Если это встроенная функция, вы можете ввести x как unsigned, чтобы избежать большого количества приведения. , а также вопрос > 0u.

0 голосов
/ 03 июля 2018

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...