翻译环境:源代码被转换为可执行的机器指令;执行环境:实际执行代码。 文件后缀:.c —>.obj —>.exe C程序由源程序变为可执行文件的四个阶段是:
预处理:展开头文件,宏替换,删除注释,条件编译;编译:编译器对经过预处理后的程序进行编译,检查语法,生成汇编代码;汇编:转换为二进制代码,并生成目标文件;链接:链接器对目标文件和用到的函数库进行链接,合成可执行程序,寻找对应声名生成可执行文件。注意: 当使用static在头文件定义一个变量或函数,在源文件使用extern时将会报错,二者冲突
①使用 # ,把一个宏参数变成对应的字符串。
#include<stdio.h> #define PRINT(FORMAT, VALUE) printf("the value of "#VALUE" is "FORMAT"\n", VALUE); int main() { int i=10; PRINT("%d",i+3); //the value of i+3 is 13 return 0; }② ## 可以把位于它两边的符号合成一个符号;它允许宏定义从分离的文本片段创建标识符。
#include<stdio.h> #define ADD_TO_SUM(num, value) sum##num += value int main() { int sum1, sum2, sum3 = 1; ADD_TO_SUM(3, 10); //给sum3增加10. getchar(); return 0; } 宏函数与函数: #define MALLOC(num,type) (type*)malloc(num*sizeof(type)) MALLOC(10,int); //类型作为参数 //预处理器替换之后: (int*)malloc(10*sizeof(int));宏可以增强代码可维护性,其规模与速度优于函数;宏的参数可以出现类型,但是函数做不到 注意: ①使用宏会将一份宏定义的代码插入程序。除非宏比较短,否则可能会增加程序的长度; ②宏是不可调试的。宏不能递归; ③宏由于类型无关,也就不够严谨。 ④宏可能会带来运算符优先级的问题,导致程容易出现错。
define无法正确处理指针 typedef: 关键字,在编译时处理,有类型检查功能,没有作用域限制。 ①为基本数据类型定义新的类型名 typedef unsigned int COUNT; ②为数组定义简洁的类型名称 typedef int ARR[100]; ARR arr [ ]= { } ; ③为指针定义简洁的名称 typedef char* PCH; PCH pa; #define INTPTR1 int* typedef int* INTPTR2; INTPTR1 p1, p2; INTPTR2 p3, p4; 含义分别为:声明一个指针变量p1和一个整型变量p2 声明两个指针变量p3、p4,注意: ①自定义头文件用#include" ",库文件用#include< >可以提高效率; ②#pragma once可以防止头文件重复引用;条件编译还可以防止嵌套文件中头文件重复引用。
eg.
#include<stdio.h> #define __ DEBUG__ 1 int main() { int i = 0; int arr[10] = { 0 }; for (i = 0; i < 10; i++) { arr[i] = i; #ifdef __ DEBUG__ printf("%-2d", arr[i]); //调试性的代码,为了观察数组是否赋值成功。 #endif //__ DEBUG__ } return 0; }①register:建议将定义放入寄存器。 ②auto:声明变量的生存周期为自动。 ③const:必须在定义时初始化;不可以给常量赋值。
