开发:写代码
编译器:把代码文件翻译生成计算机认识的二进制文件
GUN: gcc编译器
MSVC:Microsoft Visual C/C++编译器
IDE: 集成开发环境,文本编辑器 + 编译器 + 工程管理工具
gcc 编译的四个过程
-
预处理:
gcc -E + 文件名 -o (生成目标) 文件名.i (预处理文件)
1、把头文件进行展开
2、宏定义替代
-
编译: 把c代码翻译成汇编语言代码
gcc -S 1.i -o 1.s
-
汇编: 把汇编代码翻译成机器语言
gcc -c 1.s -o 1.o
-
链接: 生成可执行程序(可执行文件 以“.out”结尾,一般可以省略)
gcc 1.o -o 1
-
预处理
预处理是指在程序代码实际编译之前,对代码进行一系列的处理操作。预处理器是一种能够读取代码文件并执行预处理操作的程序,它可以执行宏定义替换、文件包含、条件编译等操作,从而提供代码的效率和可读性。
(1) #include文件包含
(2) #define 宏定义
(3)#if #endif 条件编译
(4)防止头文件重复包含
1)文件包含处理
- C语言提供了 #include 命令来实现“文件包含”的操作
- 主要是指一个源文件可以将另外一个源文件的全部内容包含进来,如图所示:
2)#include <>和 #include " "
- #include语法: #include<头文件>或者#include"头文件“
- 两者的区别:
#include<系统头文件>
#include"用户自定义头文件"
3) 宏定义
- 在预处理阶段进行替换
-
宏定义的语法:
好处1:替换文本,使代码可读性更高;
#define true 1
#define false 0
好处2:替换通篇都在用的常量,便于更改常量(宏名一般用大写,以便于与变量区别)
#define PI 3.14
-
从不同角度分析:define 和 const 的区别
1. 定义常量
-
const 定义的常数是变量 带类型,(const详解参照如下网页)
#define 定义的只是个常数 不带类型。
2. 起作用阶段
define是在编译的预处理阶段起作用,而 const是在 编译、运行的时候起作用。
3. 起作用方式
-
define只是简单的 字符串替换 ,没有类型检查。
而const有对应的数据类型,是要进行判断的
//define只是简单的字符串替换会导致边界效应
#define N 2+3 //我们预想的N值是5,我们这样使用N
double a = N/2; //我们预想的a的值是2.5,可实际上a=2+3/2=3.0
如下面的事例代码所示:
#define operate1(x,y,z) (x)+(y)*(z)
#define operate2(x,y,z) x+y*z
main(){
int a=1;
int b=2;
int c=3; printf("%d\n",operate1(a+b,a+c,b+c));
printf("%d\n",operate2(a+b,a+c,b+c));
}
预处理阶段的结果:
4. define不可更改,
const可以通过指针修改(define 真常量 const 伪常量)
const伪常量:(总结:类型T 到 const 类型T 可以;反之必须进行强制转型;)
1. 指向非const类型的指针能隐示转换成指向同一或兼容类型的const限定版本的指针
int *p=0; const int* cp=p; //OK:添加限定符(int 到const int) p=cp; //错误:舍弃限定符(const int 到 int) p=(int *)cp; //OK:转型 ;可以通过指针进行改变???
2. 指向指向T指针的指针不可转换为指向指向constT指针的指针
char *p==0; const char **cpp=&p; //错误:char * 与 const char * 不是兼容类型 char * const *cpp=&p; //正确: 添加限定符(char * 到 char *const)
5. 头文件的重复,解决方式:
条件编译;避免头文件的重复包含
func1.c
#include<stdio.h>
#include "func1.h"
extern int a;
void func1(){
printf("a = %d\n",a);
}
func1.h
#ifndef __FUNC1_H__
#define __FUNC1_H__
int a = 5;
extern void func1();
#endif
func2.c
#include<stdio.h>
extern int b;
void func2(){
printf("b = %d\n",b);
}
func2.h
#ifndef __FUNC2_H__
#define __FUNC2_H__
#include "func1.h"
int b=6;
extern void func2();
#endif
main.c
#include <stdio.h>
// #include "func1.h"
// #include "func2.h"
/*
//#include"func1.h"的展开情况
#include<stdio.h>
#include "func1.h" //重复部分
extern int a;
//#include"func2.h"的展开情况
#include "func1.h" //重复部分
int b=6;
extern void func2();
*/
#ifndef __FUNC1_H__
#define __FUNC1_H__
int a = 5;
extern void func1();
#endif
#ifndef __FUNC2_H__
#define __FUNC2_H__
#ifndef __FUNC1_H__ //func1.h已经存在,所以略过该#ifndef #endif模块
#define __FUNC1_H__
int a = 5;
extern void func1();
#endif
int b=6;
extern void func2();
#endif
int main(){
func1();
func2();
}
条件编译:实现跨平台编译
//条件编译
经宏定义实现:
#include<stdio.h> int main(){ #ifdef WINDOWS printf("I am windows!\n"); #else printf("I am Linux!\n"); #endif return 0; }`