基本标示符-宏-编译连接
来源:互联网 发布:软件升级服务合同 编辑:程序博客网 时间:2024/06/07 05:14
励志做一个文艺程序员的我,发现自己还是缺少文艺细胞,所以博客名字非常直白,就是来说一说基本标示符合宏以及编译连接的过程。
首先是基本标示符,这就简单来谈四个:__FILE__,__LINE__,__DATE__,__TIME__.
第一个:__FILE__:顾名思义就是文件的存储位置,这个在打印语句中是用%s来输出的;
第二个:__LINE__:这个就是此时你的打印语句在这个C程序的第几行,用%d显示;
第三个:__DATE__:这个是显示当前的日期,包括年份、月份和日期,因为是英文的缘故,是按年,日,月来输出的;
第四个:__TIME__:这个用来显示当前的时间。
以下是代码实现
#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>int main(){printf("%s\n %d\n %s\n %s\n",__FILE__,__LINE__,__DATE__,__TIME__);system("pause");return 0;}这个就十分简单了,就不多说了。
现在说宏,宏有很多作用,但大家平时用得最多的就是定义一个全部变量。例如:
#define M 10 //这个就是这个C文件中想用10时,采用M就行,加深了代码的灵活性除了这个,宏还有很多的作用,并且宏是在预处理阶段进行的,即编译阶段就会将宏的作用体现,这个在VS里面没法看,在linux里面会发现gcc编译之后就会发现.i文件中已经实现了宏。
要注意的是,在宏里定义时,要养成一个加小括号的习惯,例如
#define ADD(a,b) a * b假如是3*5的话,会正确是输出15,但是如果a为1+2,b是4+1时,这个时候的逻辑就是1+2 * 4+1 ,这个时候的优先级是先乘法再加法,结果就是10,而不是需要的15,但如果加括号的话就是(1+2)*(4+1),出来的就是15了,同理,为了防止其他的问题,也应该给整个式子加上括号((1+2)*(4+1))。
宏在定义函数时,要进行do{函数1,函数2,...,函数n;}while(0)的操作,为的是防止函数后面的分号,和main函数里面的分号产生冲突。例如:
#define name do{函数1,函数2,...,函数n;}while(0)int main (){ name; return 0;}这时就不用在意分号了(只要你输入无误)。
同样,宏里面还能定义字符串。例如“
#define str “Hello”int mian (){ printf("str"world " \n"); return 0;}
此时,因为宏定义的邻近字符串的连接特性,可以直接采用str,而不用给str带上双引号。
宏定义里面还可以将两个连接成一个,说起来可能不是很好表达,大家看一下代码
#define M "Hello "
#define N "World "
#define MN "Hello World "
#define LINK(x,y) x##y
int main()
{
printf("%s",LINK(M, N));//此时输出就会是完整的"Hello World "
return 0;
}宏的定义还有很重要的一点,那就是条件编译,这个在我们写代码,项目的时候对我们非常有帮助,一方面可以防止头文件被重复调用,另一方面可以让我们将宏用的更加灵活,对宏的定义也更深刻,下面的也只是我的一点理解,有不足的地方还请告知。
例如:#define后一个名称,用到一半,在下面的文件中发现还有别的函数或者变量更适合这个名字,此时你可以用#undef来移除这个宏定义,那么之前你定义的那个宏定义就会失去作用,但在#undef之前还可以使用。但是这个不建议使用,假如你这样使用,或许别人有时会忽略或者没看到中间的#undef,那么会一直以为你的宏定义是之前的意思,容易造成误解, 不过要是只有你自己看的话那就随便咯。
还可以用来检测是否被定义
#if !define(symbel) //检测symbel是否被定义,没有定义的话执行下面的语句
#define symbel //没有定义,测定义symbel另一个作用:
//1
#define NAME ... //定义NAME
#if NAME 语句1 //若NAME为真,则输出语句1
#endif
//2
<pre name="code" class="html">#define NAME ... //定义NAME
#if NAME 语句1 //若NAME为真,则输出语句1
#elif NAME1 语句2 //若NAME1为真,则输出语句1
#elif NAME2 语句3 //若NAME2为真,则输出语句1
...
#endif
编译连接:
说实话。我对这个也不是很了解,而仅有的这些还是在Linux上了解的,首先建立好一个简单的C文件之后,编译这个文件,这时会进行预处理,而预处理会进行四项活动分别是:头文件展开、去注释、宏替换、条件编译。这些在linux上你将.c文件转为.i文件后可以看见采用gcc -E test.c -o test.i语句,再使用cat test.i可以进入.i文件进行查看,假如你还觉得不是很贴近计算机的方式还可以用gcc -S test.i -o tets.s,再用cat test.s进行查看汇编语言,要是你还觉得不过瘾,那就gcc -c test.s -o test.o,再用cat查看8进制或者16进制的01序列吧。
而且,本地中有很多头文件还有库函数,在编译期间并没有将这些东西编译进去,那么会在什么时候起作用呢?会在链接时,将你自己的C文件编译完成没有错误之后,和这写库函数进行统一的链接,形成一个完整的可执行文件,把可执行程序需要的所有编译过程产生的.o或者obj文件组合到一起(包括.lib),另外连接过程还会组合一些其他数据,比如次元,可执行文件头等。
- 基本标示符-宏-编译连接
- MFC中的连接符标示使用
- 标示符
- 标示符&相对标示符
- java入门-标示符与关键字和基本数据类型
- oracle10 ora-12154 无法连接指定的标示符
- orac-123154:TNS:无法解析指定的连接标示符
- c++标示符前缀
- Java标示符、关键字
- C#中@标示符
- IOS 唯一标示符
- 语法错误:标示符:“CCSet”
- 3. 标示符
- 唯一标示符
- 设备标示符
- 设备唯一标示符
- ******************** 注释,标示符,关键字 ********************
- 标示符命名规则
- 20161102
- TCP拥塞控制算法-从BIC到CUBIC
- MVC三层架构
- Java中集合List按照集合内实体类元素的指定字段排序方法
- 程序员应该知道的 关于const和static
- 基本标示符-宏-编译连接
- 在云服务器上搭建git服务器遇到的问题及解决
- php反序列化
- Git/GitHub 的使用
- 统计学相关概念及机器学习中样本相似性度量之马氏距离
- TCP与UDP的区别
- [BZOJ4034][HAOI2015]T2 树链剖分+dfs序
- mysql 安装完毕后,忘记密码
- 【安价】亚拉奈夫想要复兴贫弱男爵家的样子【内政】1