获取代码中宏定义等信息的一些手段

            获取代码中宏定义等信息的一些手段

            来源 https://www.cnblogs.com/clover-toeic/p/3849113.html

             

            1.  预编译阶段可知的信息

                 假设代码某处有宏定义如下:

            #define MACRO  2

                 则:

                 1) 查看宏名是否定义

            #if defined MACRO
                #error defined MACRO!
            #endif

                 2) 查看宏值是否某值

            #if (2 == MACRO)
                #error (2 == MACRO)!
            #endif

                 编译输出:

            test.c:3:10: error: #error defined MACRO!
            test.c:6:10: error: #error (2 == MACRO)!

                 其中,#error用于输出自定义的预处理信息,并非指示真实出现的错误。

             

            2. 编译阶段可知的信息

                 定义下述静态断言宏:

            #define CONCATE(x, y)             _CONCATE(x, y)
            #define _CONCATE(x, y)            x##y
            #define STATIC_ASSERT(exp)        typedef char      CONCATE(Assertion_Failed_at_Line, __LINE__)[(exp) ? 1 : -1]
            #define STATIC_ASSERT2(exp, str)  typedef char      CONCATE(str##_at_Line, __LINE__)[(exp) ? 1 : -1]

                 该宏巧妙地利用gcc编译器下数组下标为-1时的编译报错。其中,exp为需要检查的表达式;str为用户定制的错误信息字符串,须满足C语言变量命名规则(不要写成字符串或带空格或以数字起始等)。typedef char意在避免变量命名冲突或命名空间污染。

                 应用举例如下:

            typedef struct{
                char acRecord[32];
            }T_HIST_ALM;
            #define HIS_ALM_NUM   300     //历史告警最大数目
            
            #define HIS_ALM_BASE  0x3000  //历史告警起始地址
            #define HIS_LOG_BASE  0x4000  //历史日志起始地址
            
            int main(void){
                STATIC_ASSERT(sizeof(T_HIST_ALM) <= 20);
                STATIC_ASSERT2((HIS_ALM_BASE + sizeof(T_HIST_ALM)*HIS_ALM_NUM) < HIS_LOG_BASE,                    History_Alarm_Space_Is_Not_Enough);
                return 0;
            }

                 编译后报错如下(示例代码中省略头文件和断言宏定义,故行号显示有所出入):

            [[email protected] test1]$ gcc -o test test.c
            test.c: In function ‘main‘:
            test.c:17: error: size of array ‘Assertion_Failed_at_Line17‘ is negative
            test.c:18: error: size of array ‘History_Alarm_Space_Is_Not_Enough_at_Line19‘ is negative

                 可见,编译报错本身已提供文件名、函数名和行号信息,故断言宏内的行号可有可无。

                 静态断言可用于编译期间检查数组、堆等缓冲区溢出,以及资源分配是否足够等。

             

            3. 运行期间可知的信息

                 定义调试跟踪宏,在待日志信息前附加日志文件名、行数、函数名等信息:

            #define TRACE(fmt, args...) do{    printf("[%s(%d)<%s>]", __FILE__, __LINE__, __FUNCTION__);    printf((fmt), ##args);}while(0)

                 应用举例如下:

            int main(void){
                TRACE("Minus 128 = 0x%x!\n", -128);               
                return 0;
            }

                 运行时输出:

            [test.c(2)<main>]Minus 128 = 0xffffff80!

             

            ================ End

            相关文章
            相关标签/搜索
            每日一句
              每一个你不满意的现在,都有一个你没有努力的曾经。
            公众号推荐
               一个历史类的公众号,欢迎关注
            一两拨千金
            中彩堂zzyz,ccus时来棋牌游戏下载-时来棋牌游戏平台app最新版下载