初学c语言22(编译和链接)
一.翻译环境和运行环境
在ANSIC的任何一种实现中存在俩个不同的环境,分别为翻译环境和运行环境,翻译环境中源代码转化为可执行的机器指令(二进制指令),执行环境执行代码
1.翻译环境
翻译环境分为编译和链接,而编译又分为预处理、编译、汇编三个过程
二.预处理详解
预处理阶段主要处理的是源文件#开始的预编译指令,规则如下:
• 将所有的 #define 删除,并展开所有的宏定义。
• 处理所有的条件编译指令,如: #if 、 #ifdef 、 #elif 、 #else 、 #endif 。
• 处理#include预编译指令,将包含的头⽂件的内容插⼊到该预编译指令的位置。这个过程是递归进 ⾏的,也就是说被包含的头⽂件也可能包含其他⽂件。
• 删除所有的注释
• 添加⾏号和⽂件名标识,⽅便后续编译器⽣成调试信息等。
• 保留所有的 #pragma 的编译器指令,编译器后续会使⽤。
1.预定义符号
#include <stdio.h>int main()
{printf("%s\n", __FILE__); //进行编译的源文件printf("%d\n", __LINE__); //文件当前的行号printf("%s\n", __DATE__); //文件编译的日期printf("%s\n", __TIME__); //文件编译的时间return 0;
}
结果:
2.#define定义常量
语法:
3.#define定义宏
语法:
举例:
但这个代码存在问题:
所以得这么写:
4.宏和函数的对比
5.#运算符
功能:将一个参数转化为字符串字面量(仅能出现在带参数宏的替换链列表里)
补充:
举例:
6.##运算符
功能:将位于俩边的合成一个符号
举例:
7.#undef
功能:移除一个宏定义(与#define 对偶)
8.条件编译
功能:可以选择性编译
1.#if
常量表达式
//... 为真就执行编译#endif//
常量表达式由预处理器求值。如:
#define __DEBUG__ 1#if __DEBUG__//..#endif2.
多个分⽀的条件编译
#if
常量表达式
//...#elif
常量表达式
//...#else//...3.
判断是否被定义
#if defined(symbol)#ifdef symbol#if !defined(symbol)#ifndef symbol
4.
嵌套指令
#if defined(OS_UNIX)#ifdef OPTION1unix_version_option1();#endif#ifdef OPTION2unix_version_option2();#endif
#elif defined(OS_MSDOS)#ifdef OPTION2msdos_version_option2();#endif
#endif
9.头文件的包含
分为本地文件包含(如之前扫雷游戏中#include "game.h")和 库文件包含(如#include <stdio.h>)
查找策略:先在源⽂件所在⽬录下查找,如果该头⽂件未找到,编译器就像查找库函数头⽂件⼀样在标准位置查 找头⽂件。 如果找不到就提⽰编译错误
10.嵌套文件包含
由于头文件可能重复包含,如果工程较大会导致预处理阶段插入大量重复代码,编译压力大
有如下解决方案:
1.在每个头文件开头加上如下代码:
#ifndef __TEST_H__
#define __TEST_H__
//头⽂件的内容
#endif
或:
#pragma once