#include "stdio.h"
#define TYPE_DATA_DEFINE(name) \
name; \
unsigned char name##valid;\
#define TYPE_DATA_SET(name, value) \
name##valid = 1; \
name = value; \
#define TYPE_DATA_GET(name, value) \
(name##valid == 1 ? (value = name, 1) : 0)
#define TYPE_DATA_CLEAR(name) \
name = 0; \
name##valid = 0; \
struct hh {
unsigned char TYPE_DATA_DEFINE(max);
unsigned char TYPE_DATA_DEFINE(min);
};
int main(void)
{
struct hh hhs = { 0 };
unsigned char tmp;
if (SSWL_TYPE_DATA_GET(hhs.max, tmp)) {
printf("info, tmp:(%u)", tmp);
} else {
printf("info, tmp:(%u)", tmp);
}
return 0;
}
我想根据C语言代码的类型添加另一种类型。该类型保留了原来的任意类型,但在此基础上增加了一个unsigned char类型的有效字段。
但是我遇到了两个问题。不知道有没有人有好的解决办法:
我考虑了 C11 的 _Static_assert 语法和 GNU 的 #define static_assert(condition)
形式为 typedef char static_assert_failed[(condition) ? 1 : -1],还有更好的办法吗?
- 使用 GET 和 SET 时,如果类型不匹配,编译器不会发出警告。然而,这对于编写安全的 C 代码是不允许的。如何 我们可以在保留参数类型的同时保持上述功能吗 检查功能。
宏不是函数。所提供的代码中唯一的函数是
main()
。
宏调用扩展到 C 源代码。如果您想要有关类型不完全匹配的赋值的警告,那么这与您对宏的使用没有特别关系,因为此类警告将基于生成的扩展代码。
你的编译器可能会发出什么诊断信息是你和它之间的事。任何特定的人可能有也可能没有诊断您所询问的情况的设施。
如果您碰巧正在使用 GCC,那么打开
-Wconversion
可能会得到您想要的诊断(我含糊其辞,因为我不确定我是否完全理解您想要的东西)。其他模拟 GCC 命令行选项(Clang、icc 等)的编译器也可能支持该选项。不模拟 gcc 选项的编译器可能有自己的版本。
- 我的宏不支持数组定义。有没有好的方法来实现数组定义?
我不认为你的宏堆栈有什么特别好的地方。但是,您可以通过添加维度/索引参数来使其支持数组。请注意,宏参数可以根本不包含任何标记,这就是您将与标量一起使用的内容。示例:
#define TYPE_DATA_DEFINE(name, dim) \
name dim; \
unsigned char name##valid;\
#define TYPE_DATA_SET(name, index, value) \
name##valid = 1; \
name index = value; \
#define TYPE_DATA_GET(name, index, value) \
(name##valid == 1 ? (value = name index, 1) : 0)
#define TYPE_DATA_CLEAR(name, index) \
name index = 0; \
name##valid = 0; \
struct hh {
unsigned char TYPE_DATA_DEFINE(scalar,);
unsigned char TYPE_DATA_DEFINE(array, [3]);
};
int main(void)
{
struct hh hhs = { 0 };
unsigned char tmp = 42;
if (TYPE_DATA_GET(hhs.scalar,, tmp)) {
printf("info, tmp:(%u)", tmp);
} else {
printf("info, tmp:(%u)", tmp);
}
if (TYPE_DATA_GET(hhs.array, [1], tmp)) {
printf("info, tmp:(%u)", tmp);
} else {
printf("info, tmp:(%u)", tmp);
}
return 0;
}
如果您希望数组成员具有有效性标志数组,那么您可以修改上面的内容来实现。
但是不要。不要做任何这样的事情。这太糟糕了,而且没有办法让它变得更好。我不仅不喜欢它的实现,也不喜欢每个成员有效性标签的整个基本概念。