预处理与宏定义

本文详细介绍了C语言的预处理过程,包括头文件包含、宏定义(无参宏、带参宏)、条件编译等。通过实例展示了宏定义如何影响代码行为,并对比了宏函数与普通函数的区别。同时,讲解了条件编译的使用,以及连接符`##`的功能。文章还包含了条件编译在字符串大小写转换中的应用。
摘要由CSDN通过智能技术生成

预处理与宏定义

1、 C语言编译过程

1、预处理: 头文件包含、宏替换、条件编译、删除注释 (不做语法检查)

gcc  -E  hello.c -o hello.i  

2、编译: 将预处理后的文件生成汇编文件 (语法检查)

gcc  -S  hello.i -o hello.s 

3、汇编: 将汇编文件编译成二进制文件

gcc  -c  hello.s -o hello.o

4、链接:

gcc  hello.o   -o  hello

一步到位: gcc xxx.c -o xxx
gcc可以同时编译多个文件:gcc a.c b.c c.c … -o 可执行文件名(不用加头文件)

参数: -D macro … 编译时指定一个宏,相当于C语言中的 #define macro

2、头文件

在这里插入图片描述

防止头文件重复包含

在这里插入图片描述

3、宏定义

3.1无参数的宏定义

#define 宏名 字符串

例: #define PI 3.141926
注: 
1.在编译预处理时,将程序中在该语句以后出现的所有的PI都调用3.141926代替
2.这种方法使用户能以一个简单的名字代替一个长的字符串
3.在预编译时将宏名替换成字符串的过程称为“宏展开”
4.宏定义,只在宏定义的文件中起作用

终止宏的作用范围:#undef
在这里插入图片描述

3.2带参数的宏(宏函数)

在这里插入图片描述

#include<stdio.h>
//宏展开 本质就是 替换
#define MY_MUL1(a,b) a*b 
#define MY_MUL2(a,b) ((a)*(b)) 

void test01()
{
	printf("%d\n",MY_MUL1(10,20)); //MY_MUL1(10,20) == 10*20
	
	//MY_MUL1( 10+10, 20+20 ) == 10+10*20+20
	printf("%d\n",MY_MUL1(10+10,20+20)); //230  不能保证完整性

	//MY_MUL2( 10+10, 20+20 ) == ((10+10)*(20+20))
	printf("%d\n",MY_MUL2(10+10,20+20)); //800  保证完整性

	return;
}
int main(int argc,char *argv[])
{
	test01();
	return 0;
}

3.3 带参数的宏(宏函数)和普通函数有啥区别

带参数的宏(宏函数):调用多少次就会展开多少次,执行代码的时候没有函数调用过程,也不需要函数的输入栈,所以带参数的宏 浪费了空间,节省了时间。
带参数的函数:代码只有一份,存在代码段中,调用的时候去代码段读取函数指令,调用的时候要压栈(保存调用函数前的相关信息),调用完出栈(恢复调用函数前的相关信息),所以函数浪费了时间节省了空间。

4 条件编译

在这里插入图片描述

#include<stdio.h>

#define MY_MAX(a,b) a>b ? a:b
#define MY_MIN(a,b) a<b ? a:b

//字符串大小写转换
void test01()
{
    char buf[30]="";
    printf("please enter:");
    fgets(buf,sizeof(buf),stdin);
    buf[strlen(buf)-1]=0;
    int i=0;
    while(buf[i]!='\0')
    {
#if 1
        if(buf[i]>='A' && buf[i]<='Z')
        {
            buf[i]=buf[i]+32;
        }
#else 
        if(buf[i]>='a' && buf[i]<='z')
        {
            buf[i]=buf[i]-32;
        }
#endif
        i++;
    }

    printf("%s \n",buf);
}


int main()
{
    test01();
    int ret=MY_MAX(211,985);
    printf("%d\n",ret);
    return 0;
}

5 关于##

##被称为连接符(concatenator),用来将两个Token连接为一个Token。
注意:这里连接的对象是Token即可,而不一定是宏的变量。

#include<stdio.h>
#define NAME(n) int_name##n
int main()
{
	int NAME(a);
	int NAME(b);
	NAME(a)=211;
	NAME(b)=985;
	
	printf("%d\n",NAME(a));
	printf("%d\n",NAME(b));
	
	return 0;
}

在这里插入图片描述

  • int NAME(a); int NAME(b); 在经过预处理后这一声明变为:int int_namea; int int_nameb;
  • 可以看出,预编译时,宏参数n被替换,并和name连接成一个整体,然后整体替换NAME宏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值