gcc的编译过程
1.预处理:
展开头文件、宏替换等,处理一切预处理指令(凡是以#号开头的语句)
头文件的作用:声明了函数原型(以便于编译器检测传参)、声明了外部全局变量、定义了数据结构和宏等。
2.编译:
进行语法、语义、词法分析,最终把C语言程序编译成汇编语言程序。
3.汇编:
进行语法、语义、词法分析,最终把汇编语言程序汇编成机器码。
4.链接:
将程序的段内偏移地址重定位为线性地址,根据符号表链接静态运行库或目标文件。
二进制代码工具
objdump: 反汇编、查看二进制代码等
nm : 查看程序符号表
readelf: 查看ELF格式程序信息
size: 查看ELF格式程序的段大小。
程序调试工具
gdb: 命令行代码调试工具
ddd: 图形界面下代码调试工具(依赖gdb)
valgrind: 内存检测工具, 可发现内存泄漏
================= 结构体 ========================
结构体: 构造一种新的数据类型,用来对已有的数据进行封装。
函数: 编写一段代码,对程序功能模块进行封装。
封装一个学生的基本信息:
姓名
学号
性别
分数
一、定义结构体类型及变量的定义方法:
1.分别定义结构体类型和变量:
struct 类型名 {
成员1;
成员2;
成员3;
…
};
例如:
struct student {
int num;
char name[32];
char sex;
int score;
};
定义结构体变量的方法:
struct 结构体类型 变量名;
例如:
struct student stu;
2.在定义类型的同时,定义变量(不推荐!不符合编程规范):
struct 类型名 {
成员1;
成员2;
成员3;
…
}变量1, 变量2 …;
例如:
struct student {
int num;
char name[32];
char sex;
int score;
}stu1, stu2;
二、结构体变量的赋值或初始化:
1.定义后赋值:
结构体变量是一个集合,对该变量的访问时需要指明访问哪个成员,方法是:
结构体变量名.成员名 = 值;
例如:
stu.num = 20140505;
stu.score = 100;
对成员访问时要考虑到成员本身的属性,例如:
stu.name = “james” /* 错误 /
strcpy(stu.name, “james”); / 正确 */
其中name成员是一个字符数组,因此不能直接赋值,要用字符串拷贝函数。
2.初始化:
和普通变量一样,结构体可以在定义时初始化(可以整体赋值); 一旦定义完毕则禁止整体赋值(和数组类似)。
方法:
struct 类型名 {
成员1;
成员2;
成员3;
…
}变量1 = {
成员1的值, /注意初始化顺序要和成员顺序一一对应,不可跨越/
成员2的值,
成员3的值,
… /*末尾的N个成员可以不赋值,默认被初始化为0(跟数组类似) /
};
例如:
struct student {
int num;
char name[32];
char sex;
int score;
}stu1 = { / 此种形式太过复杂,可读性不高,不建议使用 /
20140505,
“james”,
‘m’,
100, / 末尾的 ,号可有可无 */
};
或
struct student stu2 = {
20140505,
“james”,
‘m’,
100,
};
内存对齐
内存对齐规则:
内存对齐有三种单位: 字、半字、字节。
宽度为4B的数据要存放在能够被4整除的地址上。 (例如32位系统中的int、long)
宽度为2B的数据要存放在能够被2整除的地址上。 (例如32位系统中的short)
宽度为1B的数据要存放在能够被1整除的地址上(任意存放)。 (例如char)
结构体的整体大小是其中最大基本类型的整数倍(如果基本类型的大小超过了系统的字长,则按系统字长计算。例如double)。
============== 内存管理===========================
程序的数据存储:
栈区: stack
内存属性:读写
产生时间:运行后
存储对象:自动型局部变量。
生命周期:同所在函数的生命周期。
堆区: heap
内存属性:读写
产生时间:malloc后。
存储对象:所有用户数据。
生命周期:malloc后,free前。
常量区: rodata(const)
内存属性:只读;
产生时间: 编译后。
存储对象:字符串常量、被const修饰的静态变量(被const修饰的auto变量不会放在该区域)。
生命周期:同该进程的生命周期。
静态区: data(static)
内存属性:读写
产生时间:编译后
存储对象:全局变量、static修饰的变量。
生命周期:同该进程的生命周期。
代码区: text
内存属性:只读、可执行。
产生时间:编译后
存储对象:指令。
生命周期:同该进程的生命周期。
static作用:
1.限定作用域:
凡是被static修饰过的任何函数、变量都只允许在本文件使用,不对外链接。
2.限定存储域:
凡是被static修饰过的数据,都放在静态区。