C语言程序环境和预处理

今天来讲一下C语言的程序环境和预处理

目录

一、C语言程序环境

1、预编译

2、编译

3、汇编

4、链接

二、C语言预处理

1、宏

2、条件编译


一、C语言程序环境

C语言从写的代码到运行起来要经过预编译,编译,汇编,和链接四个部分,下面简单讲述一下这四个部分。

1、预编译

预编译部分进行的都是一些文本工作,比如注释掉的代码,#define定义的常量, 还有宏之类的操作。C语言中还有一些预定义符号:

__FILE__    __LINE__    __DATE__    __TIME__     __STDC___

这些符号的意思分别是进行编译的源文件,文件当前所在的行号,文件被编译的日期,文件被编译的时间,编译器是否遵循ANSI C,遵循其值为1,不遵循未定义。

2、编译

编译就是把预编译处理过后的代码翻译成汇编代码的过程

3、汇编

汇编过程就是通过编译生成的汇编代码形成目标文件的过程,比如我们每一个源文件都会生成一个目标文件,目标文件在windows环境下扩展名为.obj。

4、链接

链接就是在所有目标文件之间进行合并段表,符号表的合并以及符号表的重定位。比如如果编译器报错被调用的函数未定义,那就是链接过程出了问题。

二、C语言预处理

1、宏

预处理过程中有一个概念需要详细认识一下,那就是宏。

举例下面代码

#define ADD(x) x*x

int main()
{
    int ret = ADD(5+1);
    printf("%d",ret);
    return 0;
}

按照我们的直觉我们会认为打印出结果是36,但是实际上打印出的结果是11。这是因为宏只是单纯的进行替换,并不会进行任何其他操作,这里ADD(5+1)其实就是 5+1*5+1 这样就是5+5+1,答案自然是11了。

通过这个题我们会发现一个问题,就是运算时候优先级的问题,为了解决这个问题,我们需要在宏里面加括号来明确优先级

#define ADD(x) (x)*(x)

这样就可以打印出36了,但是这样就大功告成了嘛?不不不,假如我换一段代码:

#define DOUBLE(x) (x)+(x)

int main()
{
    printf("%d",10*DOUBLE(5));
}

按照我们的直觉,这里总该打印100了吧,但是事实上这里的结果是55,这是因为10*DOUBLE(5)其实是10*5+5结果自然是55了。我们会发现宏很容易造成运算优先级的问题,对于上面的这个题来说我们需要把整体再括起来:

#define DOUBLE(x) ((x)+(x))

为了解决这个问题,我们写宏的时候一定不要吝惜我们的括号。这个时候可能有人会问了,那宏这么容易写错,那我直接写函数不久好了吗,为 什么还要宏呢?

这个问题很好啊,因为宏本质上只是单纯的替换,不存在函数调用那样的堆栈,对于一些简单的操作来说,使用宏相比函数能够极大的减少内存开销。但是也要注意,宏是没法调试的,而且宏不存在类型检查,代码容易造成不严谨的错误。

那么我们正确认识了宏之后在写宏的时候有两个要注意的点,分别是# 和## 。

#会让这个宏参数变成对应的字符串。

##是让两边的符号连接起来形成一个新的符号。

2、条件编译

有些时候我们想要一段代码在不同的情况下有时参与编译,有时不参与编译。或者是有些调试性的代码,删除可惜,保留碍事,那应该怎么做呢?

这时候就要用到条件编译了,条件编译指令一共有4条:

1  #if  判断后面的常量表达式

2 #elif  适用于多个分支的条件编译

3#else  同2

4#endif  条件编译结束标志

条件编译也可以用来判断一个符号是否被定义

#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol

这就是条件编译的用法了,条件编译通常用来完成跨平台的指令。在不同平台执行不同指令。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值