我有以下宏
[{
"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)
请让我知道是否还有其他解决方法。
答案 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
的更多信息。