380元网站建设,php做网站标题加链接,公司名字大全20000个免费,物流网站的建设论文时间过得飞快呀#xff0c;从第一篇blog到现在#xff0c;已经有三四个月的时间了#xff0c;而我们终于也迎来了C语言的最终章——程序环境和预处理#xff01;加油吧朋友们#xff0c;ONEPIECE就在眼前~
目录 一、程序的翻译环境和运行环境 二…时间过得飞快呀从第一篇blog到现在已经有三四个月的时间了而我们终于也迎来了C语言的最终章——程序环境和预处理加油吧朋友们ONEPIECE就在眼前~
目录 一、程序的翻译环境和运行环境 二、详解编译环境
三、运行环境
四、预处理详解
4.1预定义符号
4.2 小能手#define
4.2.1 #define 定义标识符
4.2.2 #define 定义宏
4.2.3 #define 替换规则
4.2.4 巧用 # 和 ##
4.2.4.1 # 的使用
4.2.4.2 ##的使用 4.2.5 带副作用的宏参数
4.2.6 宏和函数的对比
4.3 #undef 4.4 条件编译
4.5文件包含
4.5.2 嵌套文件包含 一、程序的翻译环境和运行环境
在ANSIC的任何一种实现中存在两个不同的环境 第1种是翻译环境在这个环境中源代码被转换为可执行的机器指令。 第2种是运行环境它用于实际执行代码。 test.c是文本信息的代码——源代码 || test.exe是可执行程序——二进制的指令 二、详解编译环境
编译环境其实又分为编译和链接两部分编译由编译器执行、链接由链接器执行。
编译器和链接器我们都可以在我们的电脑中搜索到 下面我们介绍一下程序的编译过程 1.组成一个程序的每个源文件通过编译过程分别转换成目标代码object code。 2.每个目标文件由链接器linker捆绑在一起形成一个单一而完整的可执行程序。 3.链接器同时也会引入标准C函数库中任何被该程序所用到的函数而且它可以搜索程序员个人的程序库将其需要的函数也链接到程序中。 其实编译还可以继续细分预编译、编译、汇编。
下面我们具体看一下每一步系统都干了些什么 我们可以看到几个阶段都强调了“符号”、“符号表”的操作其实这些操作都是在为“链接”这个阶段做铺垫。
我们举个例子假设我们的文件有两个 test.c 和 add.c 符号汇总
在 add.c 中系统汇总了一个符号(系统一般只汇总应用全局的符号) add
在 test.c 中系统汇总了符号add、main、printf(这里忽略不谈)
生成符号表
注这里汇总的每一个符号都是有其地址的在这里我们假设一下。 合并段表
而且目标文件都有其特定的格式在合并符号表时相同段的数据会合并到一起
合并符号表
合并两个符号表时将 add.c 和 test.c 中的符号表合并到一起 最终系统都是通过最后这个符号表记录的地址来找到对应的符号位置。
三、运行环境
程序执行的过程1. 程序必须载入内存中。在有操作系统的环境中一般这个由操作系统完成。在独立的环境中程序的载入必须由手工安排也可能是通过可执行代码置入只读内存来完成。2. 程序的执行便开始。接着便调用main函数。 3. 开始执行程序代码。这个时候程序将使用一个运行时堆栈stack存储函数的局部变量和返回地址。程序同时也可以使用静态static内存存储于静态内存中的变量在程序的整个执行过程一直保留他们的值。4. 终止程序。正常终止main函数也有可能是意外终止。
四、预处理详解
经过上面的学习我们可能已经忘了预处理是哪个阶段来着
它是编译的第一个小阶段。
4.1预定义符号 这些预定义符号都是语言内置的。
用例
int main()
{printf(%s\n, __FILE__);//进行编译的文件printf(%d\n, __LINE__);//文件当前的行号printf(%s\n, __DATE__);//文件被编译的日期printf(%s\n, __TIME__);//文件被编译的时间//printf(%d\n, __STDC__);//当前使用是的VS2022不遵循ANSI Creturn 0;
} 4.2 小能手#define
4.2.1 #define 定义标识符 语法#define name stuff 注意define定义标识符时最后不要加 ; 因为系统是完全把 stuff 替换到 name的位置。
相信小伙伴们对定义标识符已经很熟悉啦下面我们来新介绍一个语法
4.2.2 #define 定义宏 #define 机制包括了一个规定允许把参数替换到文本中这种实现通常称为宏macro或定义宏define macro。 下面是宏的申明方式 #define name( parament-list ) stuff 其中的 parament-list 是一个由逗号隔开的符号表它们可能出现在 stuff 中。 注意参数列表的左括号必须与name紧邻。 如果两者之间有任何空白存在参数列表就会被解释为 stuff 的一部分 举个栗子
#define ADD(x, y) (x) (y)
int main()
{printf(%d\n, ADD(3, 22));return 0;
}
是不是很神奇用宏也可以做函数的工作但是宏在传参时也有可能会发生小错误 其实宏能做的不只是这些宏能替换大部分的函数。
4.2.3 #define 替换规则
在程序中扩展#define定义符号和宏时需要涉及几个步骤。 1. 在调用宏时首先对参数进行检查看看是否包含任何由#define定义的符号。如果是它们首先被替换。//检查宏中是否存在其他#define并替换2. 替换文本随后被插入到程序中原来文本的位置。对于宏参数名被他们的值所替换。 //检查程序中的#define并替换3. 最后再次对结果文件进行扫描看看它是否包含任何由#define定义的符号。如果是就重复上述处理过程。 注意 1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏不能出现递归。 2. 当预处理器搜索#define定义的符号的时候字符串常量的内容并不被搜索。 4.2.4 巧用 # 和 ##
4.2.4.1 # 的使用 使用 # 把一个宏参数变成对应的字符串 #define PRINT(x,format) printf(#x 的值是:format\n, x)
int main()
{float Love_date 3.22;PRINT(Love_date, %.2f);return 0;
} 4.2.4.2 ##的使用 ##可以把位于它两边的符号合成一个符号。 它允许宏定义从分离的文本片段创建标识符。 注这样的连接必须产生一个合法的标识符。否则其结果就是未定义的。 4.2.5 带副作用的宏参数
当宏参数在宏的定义中出现超过一次的时候如果参数带有副作用那么你在使用这个宏的时候就可能出现危险导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。 例如 x 1; //不带副作用 x; //带有副作用 4.2.6 宏和函数的对比
宏的优点 1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。 所以宏比函数在程序的规模和速度方面更胜一筹。 2. 更为重要的是函数的参数必须声明为特定的类型 宏是类型无关的。 所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点 型等可以用于来比较的类型。 宏的缺点 1. 每次使用宏的时候一份宏定义的代码将插入到程序中。 除非宏比较短否则可能大幅度增加程序的长度每使用一次都要替换一次。 2. 宏是没法调试的。宏直接替换我们无法逐步分析。 3. 宏由于类型无关也就不够严谨。 4. 宏可能会带来运算符优先级的问题导致程容易出现错 另外为了区分宏和函数在宏和函数的命名时宏一般全大写如MAX、DOUBLE...而函数名不全大写。
4.3 #undef #undef 用于移除一个宏定义 4.4 条件编译
在编译一个程序的时候我们如果要将一条语句一组语句编译或者放弃是很方便的。因为我们有条件编译指令。
常见的条件编译指令 1.(同if else) #if 常量表达式 //操作 #endif//常量表达式由预处理器求值。 如
#if 1printf(u r a genius!\n);
#endif
//... 2.多个分支的条件编译(同if elseif else)#if 常量表达式//...#elif 常量表达式 //可以无限多//...#else//...#endif //结束标志必须有 3.判断是否被定义#if defined(symbol) #ifdef symbol //以上两种写法相同#if !defined(symbol) #ifndef symbol //以上两种写法相同 4.嵌套指令#if defined(OS_UNIX) #ifdef 条件1 //... #endif #ifdef 条件2 //... #endif #elif defined(OS_MSDOS) #ifdef 条件3 //... #endif#endif 4.5文件包含
4.5.1 头文件被包含的方式
头文件的包含有2中形式 1.包含本地文件自己的.h文件 #includexxx.h 2.包含标准库的头文件 #includexxx.h 本地文件查找
先在源文件所在目录下查找如果该头文件未找到编译器就像查找库函数头文件一样在标准位置查找头文件如果找不到就提示编译错误。
标准库文件查找
查找头文件直接去标准路径下去查找如果找不到就提示编译错误。
4.5.2 嵌套文件包含 当出现以上这种场景时就造成了文件内容的重复。
这时我们就可以使用条件编译。或者在VS中我们创建.h文件中它也会生成#pragma once 这也可以避免头文件的重复引入。