GNU工具
1. 编译工具:把一个源程序编译为一个可执行程序(gcc)
2. 调试工具:能对可执行程序进行源码或汇编级调试(gdb)
3. 软件工程工具:用于协助多人开发或大型软件项目的管理
gcc编译器
gcc hello. c - o hello
1. 预处理:将头文件或宏定义展开加到程序中
gcc - E hello. c - o hello. i
注意:不会检查语法错误
2. 编译:将源程序编译成汇编语言
gcc - S hello. i - o hello. s
注意:检查语法错误
3. 汇编:将汇编文件编译成二进制文件(目标文件)
gcc - c hello. s - o hello. o
4. 链接: 将程序运行需要的所有文件链接生成可执行文件
gcc hello. o - o hello
选项:- g: 生成调试信息
gdb调试工具
查看文件 ( gdb) l ,默认打印前10行数据
设置断点 ( gdb) b [ 行号]
查看断点情况 ( gdb) info b
运行代码 ( gdb) r :运行到断点处停止,不执行断点所在行的代码
r不能从断点处开始运行,只能从程序开头开始运行
查看变量值( gdb) p n
单步运行 ( gdb) n
( gdb) s
不会断点所在行的代码
注意:只能从断点处开始运行,不能从程序开头开始运行
恢复程序运行 ( gdb) c
删除断点:delete(del)
退出gdb:( gdb) q
数据类型
1. 整型:int 4 个字节
短整型 short 2 个字节
长整型 long 4 个字节
long long 8 个字节
sizeof : 计算数据字节长度
2. 字符型:char 1 个字节
3. 浮点型
float 单精度 4 个字节
double 双精度 8 个字节
隐式转换:int == > float
数据类型默认有符号
指针
1. 声明:
数据类型 * 指针变量名;
2. 赋值:
( 1 ) 在声明的同时初始化指针变量
int * p = & a;
( 2 ) 直接操作已有指针变量
p = & a;
3. 指针运算:
指针运算的实质就是地址的计算。
p+ n表示的实际内存单元的地址量是:
( p) + sizeof ( p的类型) * n
p- n表示的实际内存单元的地址量是:
( p) - sizeof ( p的类型) * n
++ 、-- 属于第二级优先级,从右向左结合,++ \-- 如果加在变量后面允许变量先参与其他所有的运算
如果加在变量前面先++ / -- 再运算
* p++ == > * p; p++
( * p) ++ == > * p; ( * p) ++
* ( p++ )
4. 二级指针
指向指针的变量
数组
1. 一维数组
( 1 ) 数组元素必须在声明时定义好
( 2 ) 数组名是数组首地址
( 3 ) 数组开辟的是连续的内存空间
2. 二维数组
数组元素是一维数组
指针和数组
1. 一级指针与一维数组
int a[ 3 ] ;
int * p = a;
2. 指针与二维数组
注意:二维数组的首地址不能直接赋值给指针
3. 数组指针
int ( * p) [ n] ;
n: 一维数组元素个数
* ( * ( p+ i) + j)
4. 指针数组
int * p[ n]
const
用const 声明的变量是只读型变量不允许被修改。
1. 常量化指针的对象
const < 数据类型> * < 指针变量名称> ;
< 数据类型> const * < 指针变量名称> ;
eg. int const *
const int *
常量化指针目标是限制通过指针改变其对象的值
2. 常量化指针变量
< 数据类型> * const < 指针变量名称>= < 指针运算表达式> ;
eg. int * const
3. 常量化指针变量及其对象
const < 数据类型> * const < 指针变量名> =
< 指针运算表达式> ;
eg. const int * const
void
void 型的指针变量是一种指向不确定数据类型的指针变量( 空) 。它可以通过强制类型转换让该变量指向任何数据类型的对象。
函数
1. 函数声明
2. 函数调用
3. 指针函数
返回指针的函数
4. 函数指针
指向函数的指针
函数名就是函数的入口地址
< 数据类型> (* < 函数指针名称> ) (< 参数说明列表> ) ;
5. 函数传参
(1 )赋值传参(复制)
修改形式参数的值不会影响实际参数的值
(2 )地址传参
(3 )命令行传参
int argc 命令行参数个数(包含文件名)
const char * argv[ ] 指针数组: 将命令行参数首地址作为元素
5. 递归函数
调用函数本身的函数
求3 !
结构体
特点:包含不同的数据类型
1. 定义:
定义一个结构体类型的一般形式为:
struct 结构体名
{
数据类型 成员名1 ;
数据类型 成员名2 ;
:
数据类型 成员名n;
} ;
结构体类型中的成员名可以与程序中的变量名相同,二者并不代表同一对象,编译程序可以自动对它们进行区分。
最后,总结一下结构体类型的特点:
(1 )结构体类型是用户自行构造的。
(2 )它由若干不同的基本数据类型的数据构成。
(3 )它属于C语言的一种数据类型,与整型、实型相当。因此,定义它时不分配空间,只有用它定义变量时才分配空间。
定义变量的方式
(1 )声明结构体数据类型的同时定义变量
struct 结构体名
{
成员列表;
} 变量名;
注意: 结构体名可以省略,省略后不能再使用数据类型名定义变量
struct
{
成员列表;
} 变量名;
(2 )使用数据类型名定义变量
2. 结构体的初始化:
std. a = 1 ;
std. b = ‘a’;
相同数据类型的结构题可以相互赋值
3. 结构体大小
sizeof ( ) 运算符
Linux系统字节对齐
计算结构体大小的方式:
偏移量:结构体成员变量与结构体首地址的差
(1 )成员变量的偏移量= 上一个成员变量的偏移量+ 上一个成员变量的大小
(2 )结构体的大小= 最后一个成员变量的偏移量+ 最后一个成员变量的大小
遵循原则:
(1 )结构体成员变量的偏移量必须是成员大小的整数倍
(2 )结构体大小必须是成员变量数据类型的整数倍
4. 结构体数组
5. 结构体指针
用-> 指向成员变量
struct student * p;
p-> a = 1 ;
typedef 重命名
1. typedef struct student
{
} std;
std表示为数据类型起的别名
注意:如果给结构体类型重命名,则结构体名可以省略
2. typedef struct
{
} std;
3. typedef struct
{
} std, std1;
为结构体类型起了两个别名
注意:如果使用typedef 给结构体类型重命名,则声明结构体类型的同时不能再定义变量
共用体
可以包含不同的数据类型
特点:所有成员变量共用同一块内存空间
共用体变量总是按其成员中数据长度最大的成员开辟内存空间
定义:
union 共用体名
{
成员表列;
} ; 、
4 字节对齐
字节序:字节在内存中的排列顺序
小端存储:低字节对应低地址,高字节对应高地址
大端存储:低字节对应高地址,高字节对应低地址
默认小端存储
共用体数组
共用体指针
存储类型
1. 自动变量(auto )
在函数体内声明的局部变量默认都是自动变量
2. 寄存器变量(register )
用register 声明的变量直接存放在CPU的寄存器上
3. 外部变量( extern )
(1 )extern 声明的函数表示该函数是从别的文件中引用过来的
(2 )extern 声明的变量表示该变量是从别的文件中引用过来的,不在本文件中开辟空间
(3 )在所有函数体下面定义的全局变量无法被函数识别,除非在函数体内用extern 声明
4. 静态变量(static )
(1 )static 声明的静态局部变量只初始化一次,变量的生命周期不会随着函数调用的结束而结束,函数下一次调用时该变量的初始值是上一次调用结束时该变量的值
(2 )static 声明的函数只能被本文件使用,不能被其他外部文件引用
(3 )static 声明的全局变量只能被本文件使用,不能被其他外部文件引用
: vsp : 在同一个vi编辑器中打开多个文件
多文件编程
头文件:
条件编译
优点:防止头文件重复定义
格式:
……
< > :在系统中寻找头文件
“”:在当前目录寻找头文件
内存区域的划分
1. 全局区/ 静态区
存放全局变量和静态变量
初始化
未初始化:默认值为0
程序结束后释放变量
2. 栈区
由系统自动分配和释放
默认值:随机值
自动变量和函数都是在栈区里开辟空间
3. 堆区
由程序员手动申请和释放内存,如果没有手动释放,则可能会被操作系统回收
动态分配函数
#include <stdlib.h>
void * malloc ( size_t size) ;
功能:在堆区开辟指定大小的内存空间
参数:指定内存空间的大小
返回值:成功:所开辟内存的首地址
失败:NULL
Segmentation fault ( core dumped)
段错误:(1 )代码溢出
(2 )指针操作有误. 程序中出现了野指针
野指针:指向一块未知的内存空间
NULL :表示地址为0 的内存空间,不允许被读写
void free ( void * ptr) ;
功能:释放指针指向的内存空间(必须是由动态分配函数申请)
参数:内存空间的首地址
返回值:无
4. 常量区
存放常量
int add(int a, int b)
{
retrun a+ b;
}
add ( a, b) ;
add ( 1 , 2 ) ;
char a[ ] = "hello" ;
char * p = "hello" ;
#define N 5
5. 程序代码区
存放二进制的可执行指令
Make工程管理工具
自动编译管理器,能够根据文件时间戳自动发现更新过的文件而减少编译的工作量
调用make工具时自动检测上一次调用make工具后文件时间戳是否更新,如果更新了,则重新编译该文件,否则不再重复编译
Makefile
格式:将命令行下的编译命令倒着写
gcc -c main.c -o main.o
gcc -c add.c -o add.o
gcc main.o add.o -o main
目标文件:依赖文件
< TAB键> 编译命令
调用:直接输入make
变量类型:
(1)用户自定义变量
(2)预定义变量
CFLAGS C编译器的选项,无默认值。
RM 文件删除程序的名称,默认值为rm -f
(3)自动变量
$@ 目标文件的完整名称
$^ 所有不重复的目标依赖文件,以空格分开
$* 不包含扩展名的目标文件名称
$< 第一个依赖文件的名称
伪目标:
.PHONY:目标名
用伪目标声明目标后,make不会再在当前目录下寻找有没有同名的目标文件,智慧之星Makefile中的代码