服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言预编译#define(预处理)

C语言预编译#define(预处理)

2022-11-20 16:28不知名小赖 C/C++

这篇文章主要介绍了C语言预编译#define(预处理),#define 机制包括了一个机制,允许把参数替换到文本中,这种实现通常称为宏或者宏定义,下文更多的相关资料介绍需要的小伙伴可以参考一下

一、预定义符号

预定义符号是系统本身定义的:

  • FILE 进行编译的源文件的位置
  • LINE 文件当前的行号
  • DATE 文件被编译的日期
  • TIME 文件被编译的时间
  • STDC 如果编译器遵循 ASNSI C,其值为1,否者未定义

C语言预编译#define(预处理)

二、#define 定义标识符

语法:#define name stuff (用stuff替换name)

#define MAX 100   
#define STR "hehe"
int main()
{
	int max = MAX;
	printf("%d
", max);  //输出100
	printf("%s
",STR);   //输出 hehe
	return 0;
}

三、#define 定义宏

  • #define 机制包括了一个机制,允许把参数替换到文本中,这种实现通常称为或者宏定义
  • 宏的申明方式:#define name(parament-list) stuff 其中的parament-list是一个由逗号隔开的符号表,他们可能出现在stuff中。
  • 注意:参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会解释为stuff 的一部分。
#define SQUARE(X) X*X
int main()
{
	int ret = SQUARE(5);
	printf("%d
",ret); //输出25
	return 0;
}

上面的宏定义代码存在一定的问题: 如果我们换一个参数(将5换成5+1)输出的不是36而是11为什呢?

#define SQUARE(X) X*X
int main()
{
	int ret = SQUARE(5+1);//替换之后就是(5+1*5+1 = 11)
	printf("%d
",ret);//输出11
	return 0;
}

没加括号
因此,用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或临近操作符之间不可预料的相互作用。

正确的代码:

#define SQUARE(X) (X)*(X))
int main()
{
	int ret = SQUARE(5+1);
	printf("%d
",ret);//输出36
	return 0;
}

四、#define 替换规则:

  • 一, #define NAME “lisa”
    程序中有"NAME",但”“内的东西不会被宏替换。
  • 二,宏定义前面的那个必须是合法的用户标识符
  • 三,宏定义也不是说后面东西随便写,不能把字符串的两个”“拆开。
  • 四: #define NAME “lisa”
    程序中有上面的宏定义,并且,程序里有句:
    NAMELIST这样,不会被替换成"lisa"LIST
  • 五,宏不能出现递归

五、#和## 两个符号(少见)

#的作用:把参数插入到字符串中

如果我们想要实现一个代码:把参数插入到字符串中 用到“#”

C语言预编译#define(预处理)

这里参数a,b就插入到了字符串中了
 ##的作用:可以把位于它两边的符号合成一个符号,它允许宏定义冲从分离的文本片段创建标识符。

C语言预编译#define(预处理)

图中的三句代码是等价的:

printf(“%d ”,AGE(lisa,24));
printf(“%d ”,AGE(lisa##24));
printf(“%d ”,AGE(lisa24));

六、宏和函数的对比

函数和宏都能实现求两个数的最大值

//函数
int Max(int x, int y)
{
	return (x > y ? x : y);
}
//宏
#define MAX(X,Y) ((X)>(Y)?(X):(Y))
int main()
{
	int a = 10;
	int b = 20;
	int max = Max(a, b); //输出20
	printf("%d
",max);
	max = MAX(a, b);
	printf("%d
", max); //输出20
	return 0;
}

通过分析上面的代码实现用宏比用函数会更好,有两个原因:

  • 用于调用函数和从函数返回的代码可能比实际执行的这个小型计算工作所需要的时间更多,所以宏比函数在程序的规模和速度方面更胜一筹。
  • 函数的参数必须申明为特定的类型。所以函数只能在类型合适的表达时式上使用。反之宏是与类型无关的。

当然宏相比函数也有劣势的地方:

  • 每次使用宏的时候,一份宏定义的代码将替换插入到程序中。除非宏比较短,否者可能大幅度增加程序的长度。
  • 宏没法调试
  • 宏由于类型无关,也就不够严谨
  • 宏可能会带来运算符优先级的问题,导致程序容易出错。

#define定义宏和函数的对比表格

属性 #define定义宏 函数
代码长度 每次使用时宏代码都会被插入到程序中除了非常小的宏之外,程序的长度会大幅度增长 函数的代码只出现在一个地方,每次使用这个函数时,都调用那个地方的同一份代码
执行速度 更快 存在函数的调用和函数的额外开销,所以速度相对慢一些
操作符优先级 宏参数的求值是在所有周围表达式的上下文环境里,除非加上括号,否者邻近操作符的优先级可能产生不可预料的结果,所以建议宏在书写的时候多用括号 函数参数只在函数调用的时候求值一次,它的结果值传递给函数。表达式的求值结果更容易预测。
带有副作用的参数 参数可能被替换带宏中的多个位置,所以带有副作用的参数求值可能会产生不可预料的结果 函数参数只在传参的时候求值一次,结果更容易控制
参数类型 宏的参数与类型无关,只要对参数的操作是合法的,它就可以适用于任何参数类型 函数的参数与类型有关,如果参数的类型不同,就需要不同的函数,即使他们执行任务是不同的
调试和递归 宏不方便调试,不能递归 函数可以逐语句调试,可以递归

命名约定:把宏名全部大写,函数名不要全部大写。

七、#undef

#undef 指令用于移除一个宏定义

当#undef 移除宏定义,再次使用报错。如图 :

C语言预编译#define(预处理)

到此这篇关于C语言预编译#define(预处理)的文章就介绍到这了,更多相关C语言预处理内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文地址:https://blog.51cto.com/u_15542682/5245002

延伸 · 阅读

精彩推荐
  • C/C++小菜编程成长记(一 面试受挫——代码无错就是好?)

    小菜编程成长记(一 面试受挫——代码无错就是好?)

    请用C++、Java、C#或VB.NET任意一种面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符号,得到结果。...

    小菜5152021-04-14
  • C/C++QT网络编程Tcp下C/S架构的即时通信实例

    QT网络编程Tcp下C/S架构的即时通信实例

    下面小编就为大家带来一篇QT网络编程Tcp下C/S架构的即时通信实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    Creator9232021-05-29
  • C/C++C语言文件操作详情(二)

    C语言文件操作详情(二)

    这篇文章主要介绍了C语言文件操作详情,文章基于上一篇文章的内容继续展开C语言文件操作的相关详情,需要的小伙伴可以参考一下...

    不知名小赖4992022-11-20
  • C/C++C语言三子棋游戏的简单设计

    C语言三子棋游戏的简单设计

    这篇文章主要为大家详细介绍了C语言三子棋游戏的简单设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    懂的都懂乀3982022-01-25
  • C/C++C语言实现稀疏矩阵

    C语言实现稀疏矩阵

    这篇文章主要为大家详细介绍了C语言实现稀疏矩阵的代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Doublekai7362021-05-11
  • C/C++C++静态成员函数不能调用非静态成员变量(详解)

    C++静态成员函数不能调用非静态成员变量(详解)

    下面小编就为大家带来一篇C++静态成员函数不能调用非静态成员变量(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过...

    C++教程网11402021-04-23
  • C/C++OpenCV计算轮廓长度/周长和面积

    OpenCV计算轮廓长度/周长和面积

    这篇文章主要为大家详细介绍了OpenCV计算轮廓长度/周长和面积,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    我有一個夢想12822021-11-17
  • C/C++C++中共用体的定义与应用总结

    C++中共用体的定义与应用总结

    共同体的定义类似结构体,不过共同体的所有成员都在同一段内存中存放,起始地址一样,并且同一时刻只能使用其中的一个成员变量...

    C++教程网6642021-01-07