Misra兼容宏,C中为2的幂

时间:2018-07-02 20:48:29

标签: c misra

我有以下宏

[{
    "releaseDate": "05/22/18",
    "sqlServerVersion": "N/A",
    "software": "SoftwareA",
    "releaseName": "4.3.13.0",
    "releaseNote": "Note1",
    "type": "Bug",
    "productsAffected": "Product1",
    "id": "140804",
    "Type": "Patched bug"
}, 
{
    "releaseDate": "06/05/18",
    "sqlServerVersion": "SQL 2012",
    "software": "SoftwareB",
    "releaseName": "18.1.18156.02",
    "releaseNote": "Note2",
    "type": "Bug",
    "productsAffected": "Product2",
    "id": "141406",
    "Type": "Patched bug"
},
{
    "releaseDate": "06/05/18",
    "sqlServerVersion": "SQL 2016",
    "software": "SoftwareC",
    "releaseName": "4.0.94.06",
    "releaseNote": "Note3",
    "type": "Bug",
    "productsAffected": "Product3",
    "id": "141623",
    "Type": "Patched bug"
}]

为了使它符合misra,我尝试了

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

但这仍然不符合misra的要求,因为如果代码如下所示

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

misra工具将抱怨未签名的数字,而不是已签名的数字0 uint8_t val = 4; if(POWER_OF_TWO(val)) { .. }

如果对val的声明进行了签名例如((x) > 0)

我认为唯一的出路是考虑给该宏赋予正数并将代码更改为int8_t,即

((x) != 0u)

请让我知道是否还有其他解决方法。

2 个答案:

答案 0 :(得分:6)

使用静态内联函数而不是宏。 (无论如何,MISRA建议不要使用“宏函数”,请参见this SO question,因此在任何情况下都应这样做。)一旦是内联函数,则可以将x键入为无符号,以避免大量转换,因为以及> 0u问题。

答案 1 :(得分:3)

编辑:

Lundin在评论中指出,MISRA C:2012截至2018年尚不支持C11,因此以下答案很遗憾将无法完全满足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));
}

或者,结合Doug Currie和Lundin的建议以使用内联函数(前缀/后缀安全):

#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;
}

您可以在CppReference或C11标准草案的6.5.1.1部分中找到有关_Generic的更多信息。