【1】gcc编译器
1.预处理:
处理 ‘ # ‘ 开头的,将内容单纯替换
gcc -E xxx.c -o xxx.i
2.编译:
将 .i 编译生成汇编文件
gcc -S xxx.i -o xxx.s
3.汇编:
将汇编文件生成不可执行的二进制文件
gcc -c xxx.s -o xxx.o
4.连接:
将多个二进制文件和库链接生成可执行文件
gcc xxx.o xxx2.o -o xxx
gcc -c xxx.c -o xxx.o
-ESc .iso
2> gcc的选项
-c,只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
-o output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
-g,产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。
-O,对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。
-O2,比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。
-Idirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。
-Ldirname,将dirname所指出的目录加入到程序函数档案库文件的目录列表中,是在链接过程中使用的参数。
【2】gdb调试工具
编译不保存,执行报错的调试方法:
工具调试 、 使用打印语句调试
**gcc -g test.c** ----> 通过-g 生成可执行程序<br /> **gdb a.out**<br /> **l:**查看文件<br /> **b 行号/函数名:**设置断点<br /> **info b:**查看断点情况<br /> **d num(断点编号):**删除断点<br /> **r:**运行代码<br /> **p 变量名:**查看变量的值<br /> **s/n:**单步运行<br /> **help:**帮助<br /> **q:**退出
【3】make
1.工程管理器,顾名思义,是指管理较多的文件
Make工程管理器也就是个“自动编译管理器”,这里的“自动”
是指它能构根据文件时间戳自动发现更新过的文件而减少
编译的工作量,同时,它通过读入Makefile文件文件的内容
来执行大量的编译工作。
2.make工具的作用
当项目中包含多个c文件,但只对其中1个文件进行了修改,那用gcc编译会将所有的文件从头编译一遍,这样效率会非常低;所以通过make工具,可以查找到修改过的文件(根据文件**时间戳**),只对修改过的文件进行编译,这样大大减少了编译时间,提高编译效率<br />
3.Makefile是Make读入的唯一配置文件
4.Makefile编写格式
基本格式:
目标 : 依赖(文件)
目标的实现,需要通过依赖的文件
可以没有目标只有依赖。
1、只有目标没有依赖
目标:<br /> <tab>命令<br /> <br /> 执行make默认执行第一个**目标**。<br /> **make 目标 **----> 执行指定目标对应的命令<br />
2、有目标有依赖 (多个文件实现一个项目)
**目标 : 依赖(文件)**<br /> **<tab>执行命令**<br /> <br /> 分文件:<br /> **.h :**头文件<br /> **包含内容:**<br />**1.包含其他头文件**<br />**2.函数声明**<br />**3.构造数据类型**<br />**4.宏定义**<br />**5.重定义名**<br />**6.全局变量**<br /> <br /> 自己定义的头文件用 **" "** <br /> #include **"**xxx.h**"**<br /> 系统定义的头文件用 **< >** <br /> #include **<**stdio.h**>**<br /> <br /> **.c**:函数功能对应的多个.c <br /> **main.c** ----> main函数<br />
3.变量:
1)自定义变量:
VAR=值 $(变量)得到变量的值<br /> <br /> **=** : 递归方式展开<br /> **:=** : 直接赋值<br /> **+=** : 追加新的值 递归方式展开<br /> **?=** : 判断之前是否定义,如果定义了,不重新赋值,<br />否则赋值<br />
2)预定义变量
**CC** 默认值为cc,与**gcc**同<br /> **RM **默认值为**rm -f **<br /> **CFLAGS** 无默认值,一般为**C**编译器的选项<br /> **OBJS **一般为目标文件**xx.o**<br />
3) 自动变量:
**$<** 第一个依赖文件的名称<br /> **$@** 目标文件的完整名称<br /> **$^** 所有不重复的目标依赖文件,以空格分开
**% ** 匹配所有<br />
【4】条件编译
一、根据宏是否定义,其语法如下:
#ifdef <macro><br /> ……<br /> #else<br /> ……<br /> #endif
二、根据宏的值是否为真,其语法如下:
#if <macro><br /> …<br /> #else <br /> …<br /> #endif
三、根据宏是否定义,作用:防止头文件重复包含
#ifndef <macro><br /> #define <macro><br /> ....<br /> #endif <br />
练习:
1.int main()
{
int a,b,c,d;
a=10;
b=a++;
c=++a;
d=10a++;
printf(“b,c,d:%d,%d,%d”,b,c,d);
return 0;
}
2.32位
typedef union {
long i;
int k[5];
char c;
} DATE;
struct data {
int cat; /4
DATE cow; /20
double dog;/8
} too;
DATE max;
printf(“%d”,sizeof(struct date)+sizeof(max));
的执行结果是 52
3.#define DOUBLE(x) x+x ,i = 5DOUBLE(5); i 是多少?
4.请找出下面代码中的所有错误
说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”
#include
#include
int main()
{
char src=”hello,world”;
char dest=NULL;
int len=strlen(src);
dest=(char)malloc(len);
char d=dest;
char s = &src[len-1];
while(len—!=0)
d++=s—;
d = ‘\0’;
printf(“%s”,dest);
free(dest);
dest = NULL;
return 0;
}
5.Void GetMemory(char *p, int num)
{
p = (char )malloc(num);
}
void Test(void)
{
char str = NULL;
GetMemory(&str, 100);
strcpy(str, “hello”);
printf(“%s\n”,str);
}
请问运行Test 函数会有什么样的结果?
段错误
char p = NULL;
p = ‘a’;
6.char GetMemory(void)
{
char p[] = “hello world”;
char p = malloc(32);
strcpy(p, “hello world”)
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(“%s\n”, str);
}
请问运行Test 函数会有什么样的结果?