0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【GCC编译优化系列】宏定义名称与函数同名是一种什么骚操作?

嵌入式物联网开发 来源:嵌入式物联网开发 作者:嵌入式物联网开发 2022-12-08 08:43 次阅读

【GCC编译优化系列】宏定义名称与函数同名是一种什么骚操作?

如果说宏定义时C语言的精髓,那么当你看到这样的宏定义代码的时候,你一定会感慨,什么时候把这个精髓敲掉,我不要了!

1 写在前面2 问题描述3 问题分析4 问题总结5 更多分享

1 写在前面

有一天,在逛RT-Thread技术论坛时,看到这么一个问题,说某份代码中,宏定义的名称竟然与函数同名。怎么回事?

你可以去参考下原贴是怎么说的:

RT-Thread-条件编译的宏和函数名一样是否不妥RT-Thread问答社区 - RT-Thread

2 问题描述

如下图所示:

image-20221205011209795

**因为这个同学的代码编译不过,所以他就提出了这样的疑问:**究竟在C语言中宏定义名称能不能与函数名同名?

3 问题分析

为了解释这个问题,我特意找了一些伪代码。

举个例子,假如有这样的代码片段:

#define TEST_FUNC test_func
 #define TEST_FUNC1void test_func(void)
 {
 ​
 }
 ​
 void TEST_FUNC1(void)
 {
 ​
 }
 ​
 void jx_gatt_event_loop(void)
 {
 #ifdef TEST_FUNC
     TEST_FUNC(); //编译通过
 #endif
 #ifdef TEST_FUNC1
     TEST_FUNC1(); //编译失败
 #endif
 }

**那么 **TEST_FUNC1 这边就会报错,但是 TEST_FUNC 是不会报错的:

error: expected identifier or '(' before 'void'
   726 | void TEST_FUNC1(void)

查看一下预处理后的代码长啥样:

3664 
 3665 
 3666 void test_func(void)
 3667 {
 3668 
 3669 }
 3670 
 3671 void (void)
 3672 {
 3673 
 3674 }
 3675 
 3676 void jx_gatt_event_loop(void)
 3677 {
 3678 
 3679     test_func();
 3680 
 3681 
 3682     ();
 3683 
 3684 }
 3685

很明显TEST_FUNC1全被替换成空了,自然编译要报错。

尝试把 #define TEST_FUNC1 注释掉,编译没有问题,因为预处理后的代码长这样:

3666 void test_func(void)
 3667 {
 3668 
 3669 }
 3670 
 3671 void TEST_FUNC1(void)
 3672 {
 3673 
 3674 }
 3675 
 3676 void jx_gatt_event_loop(void)
 3677 {
 3678 
 3679     test_func();
 3680 
 3681 
 3682 
 3683 
 3684 }

**通过上面的代码分析,以及预处理后的文件的对比,我们可以发现,宏定义的名称与函数同名,本身并没有问题;但是如果宏定义对应的函数名,没有被定义,但代码的上下文又调用了这个函数(宏),那么编译上肯定是会报错的,因为 **找不到这个函数

4 问题总结

  • 先不考虑写代码的规范性,如果单从语法上考虑,看看预处理后的文件有助于帮助排查问题;
  • 在C语言的教科书中,并没有提到宏定义的名字不能与函数同名;所以这个根本就不是语法规则的限制;
  • 代码是首先是给人读的,其次才是给机器运行的;所以我个人是不太推荐这种过于隐晦的写法;可读性将大打折扣;
  • 如果在代码协作中看到这样的代码,我认为应该毫不犹豫地指正这个问题,同时要求修正这样的代码。

5 更多分享

[架构师李肯]

架构师李肯全网同名 ),一个专注于嵌入式IoT领域的架构师。有着近10年的嵌入式一线开发经验,深耕IoT领域多年,熟知IoT领域的业务发展,深度掌握IoT领域的相关技术栈,包括但不限于主流RTOS内核的实现及其移植、硬件驱动移植开发、网络通讯协议开发、编译构建原理及其实现、底层汇编及编译原理、编译优化及代码重构、主流IoT云平台的对接、嵌入式IoT系统的架构设计等等。拥有多项IoT领域的发明专利,热衷于技术分享,有多年撰写技术博客的经验积累,连续多月获得RT-Thread官方技术社区原创技术博文优秀奖,荣获[CSDN博客专家]、[CSDN物联网领域优质创作者]、[2021年度CSDN&RT-Thread技术社区之星]、[2022年RT-Thread全球技术大会讲师]、[RT-Thread官方嵌入式开源社区认证专家]、[RT-Thread 2021年度论坛之星TOP4]、[华为云云享专家(嵌入式物联网架构设计师)]等荣誉。坚信【知识改变命运,技术改变世界】!

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • GCC
    GCC
    +关注

    关注

    0

    文章

    107

    浏览量

    24838
  • 函数
    +关注

    关注

    3

    文章

    4331

    浏览量

    62595
  • 宏定义
    +关注

    关注

    0

    文章

    50

    浏览量

    9009
  • RT-Thread
    +关注

    关注

    31

    文章

    1289

    浏览量

    40118
收藏 人收藏

    评论

    相关推荐

    GCC编译优化系列】前后编译的两版本固件bin大小不样?

    GCC编译优化系列】前后编译的两个版本固件bin大小不样,怎么办?
    的头像 发表于 09-09 09:01 4728次阅读
    【<b class='flag-5'>GCC</b><b class='flag-5'>编译</b><b class='flag-5'>优化</b><b class='flag-5'>系列</b>】前后<b class='flag-5'>编译</b>的两版本固件bin大小不<b class='flag-5'>一</b>样?

    一种解决函数优化问题的免疫算法

    一种解决函数优化问题的免疫算法:介绍了免疫算法的基本概念,以及人工免疫系统中的克隆选择原理,基于该原理,结合遗传策略中的高斯变异算子,提出一种免疫算法来解决
    发表于 11-08 16:47 14次下载

    内联函数定义的区别介绍

    定义是C语言提供的三预处理功能的其中一种,这三预处理包括:
    发表于 12-15 15:33 2339次阅读
    内联<b class='flag-5'>函数</b>和<b class='flag-5'>宏</b><b class='flag-5'>定义</b>的区别介绍

    不带参数的定义是什么?不带参数的定义的资料介绍详细过程概述

    c语言中有定义,其中有类就是不带参数的定义
    发表于 09-04 15:38 5次下载

    GCC编译优化指南

    在控制。当然理论上控制编译工具行为的还应当有 AS ASFLAGS ARFLAGS 等变量,但是实践中基本上没有软件包使用它们。  那么我们如何控制这些变量呢?一种简易的做法是首先设置与这些
    发表于 04-02 14:36 543次阅读

    编译优化函数的影响

    编译器如gcc,可以指定不同的优化参数,在某些条件下,有些函数可能会被优化掉。
    的头像 发表于 06-22 14:58 2838次阅读
    <b class='flag-5'>编译</b>器<b class='flag-5'>优化</b>对<b class='flag-5'>函数</b>的影响

    剖析verilog2005的操作之对数函数

    也是支持的,我试了2017.4及以后的版本都可以支持,放心用。 ***友情提示:所有支持verilog2005标准的编译器都可以用这个函数,所以使用之前确定编译器是否支持这个标准,还有考虑好后期可移植性的影响 这个是可
    的头像 发表于 10-09 15:29 4422次阅读
    剖析verilog2005的<b class='flag-5'>骚</b><b class='flag-5'>操作</b>之对数<b class='flag-5'>函数</b>

    如何让gcc编译中断函数

    ),此时cpu会向栈中压入堆寄存器来保护现场,如果是异常,还会多压个错误代码,因此编写中断函数返回时要使用"iret"指令,但是gcc默认是无法
    发表于 11-26 11:06 7次下载
    如何让<b class='flag-5'>gcc</b><b class='flag-5'>编译</b>中断<b class='flag-5'>函数</b>

    C语言定义与预处理、函数函数

    系统平台上的gcc)前言本篇文章将会向大家介绍下C语言的预处理知识、定义函数、以及编译执行
    发表于 12-07 21:06 2次下载
    C语言<b class='flag-5'>宏</b><b class='flag-5'>定义</b>与预处理、<b class='flag-5'>函数</b>和<b class='flag-5'>函数</b>库

    gcc编译优化系列】如何(不)回收未发生调用的函数

    的bin文件大小势必会增加,这显然不是我们想要的。 另外,还有一种场景下,有些函数我们使用static修饰的局部函数,只在初始化的时候通过初始化列表的形式调用下,比如RT-Threa
    的头像 发表于 07-11 09:12 2927次阅读

    GCC编译优化系列】实战分析C代码遇到的编译问题及解决思路

    GCC编译优化系列】实战分析C工程代码可能遇到的编译问题及其解决思路
    的头像 发表于 07-10 23:15 1425次阅读
    【<b class='flag-5'>GCC</b><b class='flag-5'>编译</b><b class='flag-5'>优化</b><b class='flag-5'>系列</b>】实战分析C代码遇到的<b class='flag-5'>编译</b>问题及解决思路

    GCC编译优化系列】multiple-definition

    GCC编译优化系列】这种让人看不懂的multiple-definition真的有点让人头疼
    的头像 发表于 07-11 09:26 7153次阅读
    【<b class='flag-5'>GCC</b><b class='flag-5'>编译</b><b class='flag-5'>优化</b><b class='flag-5'>系列</b>】multiple-definition

    GCC编译优化系列】-specs=kernel.specs

    GCC编译优化系列GCC编译链接时候--specs=kernel.specs链接属性究竟是个
    的头像 发表于 07-11 09:25 3467次阅读
    【<b class='flag-5'>GCC</b><b class='flag-5'>编译</b><b class='flag-5'>优化</b><b class='flag-5'>系列</b>】-specs=kernel.specs

    Linux使用gcc编译程序的语法

    01. 调试相关的 在Linux使用gcc编译程序的时候,对于调试的语句还具有些特殊的语法。 gcc
    的头像 发表于 06-22 10:51 707次阅读

    C语言中函数定义和用法

    函数一种特殊的函数,与普通函数不同的是,它可
    发表于 10-11 11:32 3558次阅读
    C语言中<b class='flag-5'>宏</b><b class='flag-5'>函数</b>的<b class='flag-5'>定义</b>和用法