C 中的类型检查宏参数 [英] Typechecking macro arguments in C

查看:26
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆