程序环境和预处理
1.程序环境
环境分为翻译环境和执行环境
翻译环境
翻译环境分为两个环境:编译环境和链接
编译环境会通过一个或多个源文件生成对应的目标文件,再由链接器把目标文件和链接库生成可执行程序,因为计算机只识别二进制,所以必须需要翻译环境。
编译
编译分为三个步骤:预处理(预编译),编译和汇编
预处理(预编译)
预处理会把注释给去掉,把#define、#include等预处理指令实现功能,把#include指向的头文件的代码全部复制到对应源代码
编译
编译会把预处理的代码转换成汇编代码,进行语法分析,词法分析,语义分析,符号汇总
汇编
将汇编代码变成目标文件,不光进行语法分析,词法分析,语义分析,符合汇总还创造里一个符号表。
这个符号表会有源代码的全局变量,函数的名字和地址
链接
1.合并段表
2.符号表的合并和重定义
执行程序
程序载入内存中,有操作系统自动载入,独立的环境中的手动
预处理
_ _ FILE _ _ 文件名
_ _ LINE _ _ 文件当前行数
_ _ DATE _ _ 文件被编译的日期
_ _ TIME _ _文件被编译的时间
_ _ STDC _ _如果编译器支持C语言标准,值为1,否则未定义
预处理指令
全在预处理执行
#define
1.定义一标识符
#define x 1
#define i int
2.定义一个宏
#define a(x) x*x
左括号要与a相连
宏和函数比较
宏比函数执行速度更快,空间更少
宏参数不用标明类型,不够严谨
如果多次使用宏,宏会增长很多的代码段
宏不能调试
容易因为运算符优先级出错,不要吝啬括号
3.#和##
#会把该参数转变为字符串形式
#include<stdio.h>
#define a(x,i) printf("the"#x"is%d\n",i)
int main()
{
a(3,1);
return 0;
}
//输出 the3is1
##会把左右两边相连
#include<stdio.h>
#define a(i) printf("the"##"is%d\n",i)
int main()
{
a(1);
return 0;
}
//输出theis1
4.命名约定
宏名最好都大写
函数名字最好不要全大写
#undef
如果x被define定义了
使用#undef 就让x定义的那个标识符失效
endif
#ifdef、#if define()、#if、#elif、#else、#ifndef等条件结束标志
#ifdef和#if define()
#ifdef x 如果x被#define定义了就执行接下来语句,与#if define(x)等效
#idndef x 如果x没有被#define定义了就执行接下来语句,与#if !define(x)等效
#define x 100
#ifdef x
printf("1");
printf("2\n");
#endif
//输出12
#if、#elif、#else
#if相当于if、#elif是else if、#else是else
但都是预处理指令
防止头文件连续包含
#ifndef x
#define x
include<test.h>
#endif
//test是头文件
#pragma once