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

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

3天内不再提示

C语言必备知识编译预处理

CHANBAEK 来源:小李的创客实验室 作者: 初出茅庐的小李 2023-12-01 18:27 次阅读

C语言必备知识编译预处理

编译预处理就是在编译源代码之前进行的一系列处理,将源程序中的一些特殊命令进行展开或处理,生成扩展的源代码。这些特殊命令通常以“#”开头,占单独的行,语句尾部不需要加分号。

宏定义

(#define)是一种常见的编译预处理指令,用于定义宏,实现代码的简化和重用。

文件包含(#include)用于在源文件中引入其他文件的内容,方便代码模块化和复用。

条件编译

(#if, #else, #endif等)允许根据条件选择性地编译部分代码,提高代码的灵活性。

在预处理阶段,这些指令会被解释和处理,生成经过预处理的源代码,然后再经过编译、汇编、链接等步骤生成最终的可执行文件。这个过程有助于提高代码的可维护性和可移植性。

书写格式

以“#”开头、占单独行、语句尾不加分号。这样的规范有助于编译器正确解释和处理这些指令,同时也使得代码更加清晰易读。这样的一致性规范有助于维护代码时的可读性和可理解性。

宏定义的例子

// 定义常量

#include < stdio.h >

#define MAX_SIZE 100
#define PI 3.1415926

// 简化代码
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))


#define DEBUG   //只要定义了该宏 DEBUG_PRINT就会起作用 没有定义则不起作用 

// 字符串拼接

//#define CONCAT_STR(a,b) a##b dev平台用不了 linux未测试
#define CONCAT_STR(a,b) a b

// 条件编译
#ifdef DEBUG
    #define DEBUG_PRINT(msg) printf("Debug: %sn", msg)
#else
    #define DEBUG_PRINT(msg)
#endif




int main(void) 
{
	
	printf("5的平方是%drn",SQUARE(5));
	printf("MAX(2,3)返回较大的一个数是%drn",MAX(2,3)) ;
	DEBUG_PRINT("调试信息"); 
	printf("%srn", CONCAT_STR("你好", "World"));  // 这里会被展开为 printf("%srn", "你好, " "World");
}

这里踩到了一个坑............. dev里这个##符号竟然不能使用!看了这个博主的文章才明白 https://blog.csdn.net/leon1741/article/details/78149881,致谢致敬图片

运行结果

图片
在这里插入图片描述

宏定义使用注意事项

使用宏定义时需要注意一些事项,以确保代码的可读性和正确性。以下是一些宏定义的注意事项:

  1. 括号的使用:
    在宏定义中,为了避免优先级问题,通常在宏的参数和整体表达式外部都使用括号。例如:

    #define SQUARE(x) ((x) * (x))
    

    这样可以确保在使用时不会出现预期之外的行为。

  2. 避免副作用:
    在宏中避免使用具有副作用的表达式,因为宏是简单的文本替换,可能导致意外的行为。

    // 避免这样的宏定义
    #define INCREMENT(x) x++
    
  3. 使用大写字母:
    为了与变量和函数名区分,宏的名称通常使用大写字母。

    #define MAX_SIZE 100
    
  4. 多行宏的注意:
    如果宏跨越多行,确保在每行的末尾使用反斜杠 连接,以避免语法错误。

    #define PRINT_SUM(a, b) 
        do { 
            int sum = (a) + (b); 
            printf("Sum: %dn", sum); 
        } while(0)
    
  5. 参数的使用:
    宏参数的使用要小心,确保在宏展开时不会导致预期之外的结果。

    // 不要这样使用,可能导致问题
    #define SQUARE(x) x * x
    
  6. 条件编译:
    在使用条件编译时,确保相关的宏定义和取消定义都是正确的。

    #ifdef DEBUG
        // ...
    #endif
    

总体来说,清晰、简洁、避免副作用是设计宏定义时的关键原则。良好的宏定义可以提高代码的可读性和可维护性。

单片机中可以使用预编译来区分代码版本

如果定义了REG_CODE 这个宏且其结果是1那么就是寄存器版本代码否则就是库函数版本代码

void LED_Config(void)
{
	#if (REG_CODE)
	
	RCC- >AHB1ENR |= 1< < 2;      //GPIOC的时钟开关

	GPIOC- >MODER &= ~(3< < 2*4);//把89位清00 PC4
	GPIOC- >MODER |=  (1< < 2*4);//只是把第89位置01
	
	GPIOC- >MODER &= ~(3< < 2*5);//把10 11位清00 PC5
	GPIOC- >MODER |=  (1< < 2*5);//只是把第89位置01
	
	GPIOC- >MODER &= ~(3< < 2*6);//把11 12位清00 PC6
	GPIOC- >MODER |=  (1< < 2*6);//只是把第89位置01
	
	GPIOC- >MODER &= ~(3< < 2*7);//把89位清00  PC7
	GPIOC- >MODER |=  (1< < 2*7);//只是把第89位置01
	
	GPIOC- >OTYPER &= ~(1< < 4); //推挽模式//0xFFFF FFEF 
	GPIOC- >OTYPER &= ~(1< < 5);
	GPIOC- >OTYPER &= ~(1< < 6);
	GPIOC- >OTYPER &= ~(1< < 7);
	
	
	//假设输出状态 灯的开关
	GPIOC- >ODR |=  (1< < 4)| (1< < 5)|(1< < 6) |(1< < 7);  //默认全关
	printf("寄存器代码...rn");
	#else
	printf("LED库函数代码...rn");
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	
    GPIO_InitTypeDef  GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_OUT;
	GPIO_InitStruct.GPIO_OType  = GPIO_OType_PP;
	GPIO_InitStruct.GPIO_Pin    = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStruct.GPIO_PuPd   = GPIO_PuPd_NOPULL;
	GPIO_InitStruct.GPIO_Speed  = GPIO_High_Speed;
	
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	
	#endif
	
}

至此,预编译相关的知识点就介绍完了。

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

    关注

    180

    文章

    7533

    浏览量

    128769
  • 源代码
    +关注

    关注

    95

    文章

    2929

    浏览量

    66063
  • 代码
    +关注

    关注

    30

    文章

    4556

    浏览量

    66782
  • 编译
    +关注

    关注

    0

    文章

    615

    浏览量

    32397
  • 预处理
    +关注

    关注

    0

    文章

    32

    浏览量

    10411
收藏 人收藏

    评论

    相关推荐

    C语言预处理

    编译预处理器是C语言编译器的一个重要组成部分。很好的利用C
    发表于 06-03 17:23

    C语言常用的预处理命令

    1.基础知识(1)C语言常用的预处理命令——typedef具体可见C语言基础语法
    发表于 07-14 07:10

    c语言预处理命令以什么开头

    c语言预处理命令以什么开头,目前我并没有windows软件编写经验,对C语言的应用也仅限于各种单片机的编程,所以对
    发表于 07-20 07:00

    STM32 C语言预处理解析

    作者:张角老师(张飞实战电子高级工程师)大家好, 我们今天对C语言预处理指令做一个总结。其实C语言
    发表于 07-22 09:03

    C语言编译步骤

    嵌入式C语言开发入门——程序编译计算机语言发展过程C语言编译
    发表于 12-15 08:21

    机器语言预处理编译功能怎样

    什么是机器语言呢?机器语言预处理编译功能怎样?
    发表于 01-19 06:41

    介绍一下C语言预处理知识与宏定义原理

    系统平台上的gcc)前言本篇文章将会向大家介绍一下C语言预处理知识、宏定义、函数、以及编译执行程序所需的静态链接库和动态链接库的一些原理,
    发表于 02-11 06:35

    C语言预处理命令有哪些?

    不止。先看几个个常识性问题: A) 预处理C 语言的一部分吗? B) 包含“#”号的都是预处理吗? C)
    发表于 06-25 06:15

    C语言编译预处理

    在将一个C源程序转换为可执行程序的过程中, 编译预处理是最初的步骤. 这一步骤是由预处理器(preprocessor)来完成的. 在源流程序被编译
    发表于 09-20 18:17 47次下载

    C程序设计教程之如何进行编译预处理

    预处理是 C 语言的一个重要功能,它由预处理程序负责完成。所谓预处理是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作。当对一个
    发表于 11-02 15:47 5次下载

    浅析VerilogHDL编译系统的预处理

    。在Verilog HDL语言编译时,特定的编译指令在整个编译过程中有效(编译过程可跨越多个文件),直到遇到其他不同的
    发表于 03-26 16:10 657次阅读

    C语言预处理指令及分类

    C/C++ 程序中的源代码中包含以 # 开头的各种编译指令,这些指令称为预处理指令。预处理指令不属于 C/C++ 语言的语法,但在一定意义上可以说
    的头像 发表于 11-29 10:14 2005次阅读

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

    系统平台上的gcc)前言本篇文章将会向大家介绍一下C语言预处理知识、宏定义、函数、以及编译执行程序所需的静态链接库和动态链接库的一些原理,有助于大家更深层次的理解C
    发表于 12-07 21:06 2次下载
    C<b class='flag-5'>语言</b>宏定义与<b class='flag-5'>预处理</b>、函数和函数库

    C语言-预处理(#define、#if...)

    在C语言程序里,出现的#开头的代码段都属于预处理预处理:是在程序编译阶段就执行的代码段。
    的头像 发表于 08-14 10:13 1627次阅读

    C语言有哪些预处理操作?

    C语言预处理是在编译之前对源代码进行处理的阶段,它主要由预处理器完成。预处理器是一个独立的程序
    的头像 发表于 12-08 15:40 296次阅读
    C<b class='flag-5'>语言</b>有哪些<b class='flag-5'>预处理</b>操作?