dt| t| u| ra| tm|tra| alg| fa|
+----------+---+--------------------+---+---+---+-----+---+
|2019-04-22| 1|0e4466fb752e0ff6a...| 2| | |h5_rl| |
|2019-04-22| 1|05ce59ff55b70a805...| 4| | | null| |
|2019-04-22| 1|07bc6ebd8f9d0082d...| 2| | |h5_rl| |
它可以正常工作,但是此代码易碎。明天,我可能会将uint32_t fail_count = 0;
...
if(is_failed)
if(fail_count < UINT32_MAX - 1 )
++fail_count;
的类型从fail_count
更改为uint32_t
,而忘记更新int32_t
。
在编写我的UINT32_MAX
的函数上,有没有办法断言fail_count
是uint32_t
?
P.S。 1-我知道在C ++中很容易,但是我正在寻找一种C方式。
P.S。 2-我宁愿使用两个断言而不是依赖于编译器警告。通过if
检查数字大小应该可以,但是有什么方法可以区分类型是否为无符号?
答案 0 :(得分:22)
从C11开始,您可以使用generic selection宏根据表达式的类型产生结果。您可以在static assertion中使用结果:
#define IS_UINT32(N) _Generic((N), \
uint32_t: 1, \
default: 0 \
)
int main(void) {
uint32_t fail_count = 0;
_Static_assert(IS_UINT32(fail_count), "wrong type for fail_count");
}
您当然可以在常规assert()
中使用结果,但是_Static_assert
在编译时将失败。
一种更好的方法是根据类型调度比较,再次使用泛型选择:
#include <limits.h>
#include <stdint.h>
#define UNDER_LIMIT(N) ((N) < _Generic((N), \
int32_t: INT32_MAX, \
uint32_t: UINT32_MAX \
) -1)
int main(void) {
int32_t fail_count = 0;
if (UNDER_LIMIT(fail_count)) {
++fail_count;
}
}
答案 1 :(得分:1)
正如您提到的GCC一样,如果您不使用C11,则可以使用编译器扩展来完成此操作:
首先编写一个模拟C ++ is_same
的宏。然后使用您要比较的类型进行调用。
针对您的特定情况的最小示例:
#include<assert.h>
#define is_same(a, b) \
static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")
int main()
{
int fail_count = 0;
is_same(fail_count, unsigned int);
}
编译器断言:
<source>: In function 'main':
<source>:4:3: error: static assertion failed: "fail_count is not unsigned int"
static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")
^~~~~~~~~~~~~
<source>:9:5: note: in expansion of macro 'is_same'
is_same(fail_count, unsigned int);
^~~~~~~
请参见Demo
答案 2 :(得分:1)
即使在K&R C以及任何过去和现在的编译器下都可以使用的低技术解决方案呢?
在正确的位置放置正确的注释:
/*
* If this type is changed, don't forget to change the macro in
* if (fail_count < UINT32_MAX - 1) below (or file foobar.c)
*/
uint32_t fail_count = 0;
使用适当的封装,它应该恰好指向代码中的一个位置。 不要告诉我您在许多地方增加了失败计数。如果这样做的话 大约一个
#define FAIL_COUNT_MAX UINT32_MAX
在声明旁边?无论如何,这是更合适的代码。 不需要所有的断言魔术和火箭科学:-)