程序的编译

目录

1.程序的翻译和执行环境

2.编译+链接

2.1 翻译环境

 2.2 编译的几个阶段

 2.3 运行环境

3.预处理详解

3.1 预定义符号

 3.2 #define

3.2.1 #define定义标识符

 3.2.2 #define 定义宏

3.2.3 带副作用的宏参数

3.2.4 宏和函数比较

3.3 条件编译 

3.4 文件包含


1.程序的翻译和执行环境

程序由test.c到输出结果需要经过两个环境:翻译环境和执行环境


2.编译+链接

2.1 翻译环境

 2.2 编译的几个阶段

 2.3 运行环境

程序执行的过程

        1.程序载入在内存中

        2.调用main函数

        3.开始执行代码

        4.终止程序


3.预处理详解

3.1 预定义符号

__FILE__                //进行编译的源文件

__LINE__                //文件当前的行号

__TIME__                //文件被编译的时间

__func__                 //所处的函数 

printf("FILE:%s fun:%s LINE:%d TIME:%s", __FILE__, __func__, __LINE__, __TIME__);

 运行结果

 3.2 #define

3.2.1 #define定义标识符

语法

#define name stuff

例如

#define MAX 100

 注意:#define定义标识符时,最后不需加上;(分号)

 3.2.2 #define 定义宏

#define name( parament-list ) stuff

如:

#define SQUARE(x) x*x 

需注意的是宏把SQUARE中的x替换到了x*x中 ,这样一来会产生问题

#define SQUARE(x) x*x
int main()
{
	int a = 5;
	printf("%d\n", SQUARE(a + 1));
	return 0;
}

输出的结果为11而并非25,这是因为程序直接把a+1带到宏中,输出的是5+1*5+1的结果11

注意:

对于数值表达式进行求值的宏定义都应该加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间产生不可预料的作用

3.2.3 带副作用的宏参数

x+1;//不带副作用

x++;//不带副作用 

#define MAX(a,b) ((a) > (b) ? (a):(b))

int main()
{
	int x = 5;
	int y = 8;
	int z = MAX(x++, y++);
	printf("%d\n", x);
	printf("%d\n", y);
	printf("%d\n", z);
	return 0;
}

 以上代码输出的结果为6 10 9

造成的原因时由于具有副作用的参数所引起的问题

3.2.4 宏和函数比较

属性#define定义宏函数



每次使用时,宏代码都会被插入到程序中。除了非常小的宏之外,程序的长度会大幅度增长函数代码只出现于一个地方;每次使用这个函数时,都调用那个地方的同一份代码



更快存在函数的调用和返回的额外开销,所以相对慢一些





宏参数的求值是在所有周围表达式的上下文环境里,除非加上括号,否则邻近操作符的优先级可能会产生不可预料的后果,所以建议宏在书写的时候多些括
号。
函数参数只在函数调用的时候求值一次,它的结果值传递给函数。表达式的求值结果更容易预测。







参数可能被替换到宏体中的多个位置,所以带有副作用的参数求值可能会产生不可预料的结果函数参数只在传参的时候求值一次,结果更容易控制。



宏的参数与类型无关,只要对参数的操作是合法的,它就可以使用于任何参数类型函数的参数是与类型有关的,如果参数的类型不同,就需要不同的函数,即使他们执行的任务是
相同的。

宏是不方便调试的 函数是可以逐语句调试的

宏是不能递归的函数是可以递归的

 命名规定

宏名全部大写

函数名不要全部大写

3.3 条件编译 

在编译一个程序的时候我们如果要将一条语句(一组语句)编译或者放弃是很方便的。因为我们有条件编译指令.

常见的条件编译指令:

1.

#if     常量表达式

        //...

#endif

2.多个分支的条件编译

#if      常量表达式

        //...

#elif      常量表达式

        //...

#else      常量表达式

        //...

#endif

3.判断是否被定义

#if defined(symbol)

#ifdef symbol

#if !defined(symbol)

#ifndef symbol

4.嵌套指令

#if defined(OS_UNIX)
        #ifdef OPTION1
                unix_version_option1();
        #endif
        #ifdef OPTION2
                unix_version_option2();
        #endif
#elif defined(OS_MSDOS)
        #ifdef OPTION2
                msdos_version_option2();
        #endif
#endif

3.4 文件包含

本地文件包含

#include "filename"

查找策略:先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标准位置查找头文件。
如果找不到就提示编译错误。 

库文件包含

#include <filename.h>

 查找头文件直接去标准路径下去查找,如果找不到就提示编译错误

#progma once可以避免头文件的重复引入 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值