C 中的类型检查宏参数 [英] Typechecking macro arguments in C
问题描述
是否可以对#define 宏的参数进行类型检查?例如:
Is it possible to typecheck arguments to a #define macro? For example:
typedef enum
{
REG16_A,
REG16_B,
REG16_C
}REG16;
#define read_16(reg16) read_register_16u(reg16);
assert(typeof(reg16)==typeof(REG16));
上面的代码似乎不起作用.我做错了什么?
The above code doesn't seem to work. What am I doing wrong?
顺便说一句,我正在使用 gcc,我可以保证在这个项目中我将始终使用 gcc.代码不需要是可移植的.
BTW, I am using gcc, and I can guarantee that I will always be using gcc in this project. The code does not need to be portable.
推荐答案
这是一个老问题,但我相信我有一个一般的答案,根据 Compiler Explorer 似乎可以在 MSVC、gcc 和 clang 上工作.
This is an old question, But I believe I have a general answer that according to Compiler Explorer apears to work on MSVC, gcc and clang.
#define CHECK_TYPE(type,var) { typedef void (*type_t)(type); type_t tmp = (type_t)0; if(0) tmp(var);}
在每种情况下,如果类型不兼容,编译器都会生成有用的错误消息.这是因为它强加了用于函数参数的相同类型检查规则.
In each case the compiler generates a useful error message if the type is incompatible. This is because it imposes the same type checking rules used for function parameters.
它甚至可以在同一范围内多次使用而不会出现问题.这部分让我有些吃惊.(我认为我必须利用__LINE__"来获得这种行为)
It can even be used multiple times within the same scope without issue. This part surprises me somewhat. (I thought I would have to utilize "__LINE__" to get this behavior)
下面是我运行的完整测试,注释掉的行都会产生错误.
Below is the complete test I ran, commented out lines all generate errors.
#include <stdio.h>
#define CHECK_TYPE(type,var) { typedef void (*type_t)(type); type_t tmp = (type_t)0; if(0) tmp(var);}
typedef struct test_struct
{
char data;
} test_t;
typedef struct test2_struct
{
char data;
} test2_t;
typedef enum states
{
STATE0,
STATE1
} states_t;
int main(int argc, char ** argv)
{
test_t * var = NULL;
int i;
states_t s;
float f;
CHECK_TYPE(void *, var); //will pass for any pointer type
CHECK_TYPE(test_t *, var);
//CHECK_TYPE(int, var);
//CHECK_TYPE(int *, var);
//CHECK_TYPE(test2_t, var);
//CHECK_TYPE(test2_t *, var);
//CHECK_TYPE(states_t, var);
CHECK_TYPE(int, i);
//CHECK_TYPE(void *, i);
CHECK_TYPE(int, s); //int can be implicitly used instead of enum
//CHECK_TYPE(void *, s);
CHECK_TYPE(float, s); //MSVC warning only, gcc and clang allow promotion
//CHECK_TYPE(float *, s);
CHECK_TYPE(float, f);
//CHECK_TYPE(states_t, f);
printf("hello world
");
}
在每种情况下,带有 -O1 及更高版本的编译器都会删除结果代码中宏的所有痕迹.
In each case the compiler with -O1 and above did remove all traces of the macro in the resulting code.
使用 -O0 MSVC 将对函数的调用保留为零,但它在无条件跳转中被敲击,这意味着这不应该是一个问题.带有 -O0 的 gcc 和 clang 都删除了除了 tmp 变量的堆栈初始化为零之外的所有内容.
With -O0 MSVC left the call to the function at zero in place, but it was rapped in an unconditional jump which means this shouldn't be a concern. gcc and clang with -O0 both remove everything except for the stack initialization of the tmp variable to zero.
这篇关于C 中的类型检查宏参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!