C语言的高级编程(一)

GCC介绍

  • 格式
gcc [options] [filenames]

-c,只编译,不链接为可执行文件。生成.o文件
-o filename,输出文件。
-g,调试。
-O, -O2,对程序进行优化编译、链接。
-I dirname,将dirname所指出的目录加入到程序头文件目录列表中,实在预编译过程中使用的参数。
-L dirname,将dirname所指出的目录加到程序函数档案库文件目录列表中,是在链接过程中使用的参数。

  • GCC编译过程
    1、预处理 .c >> .i
    2、编译 .i >>.s
    3、汇编 .s >> .o
    4、链接 .o >> .exe

gcc -E test.c -o test.i: 将.c文件中的已#号开头的文件进行展开,条件编译生效。
gcc -S test.i -o test.s:生成汇编文件
gcc -c test.s -o test.o:生成对象文件
gcc test.o -o test -lm: 链接对象文件,生成可执行文件

C语言的高级编程(一)_第1张图片

调试器—Gdb调试流程

  • 使用gcc对test.c进行调试,注意一定要加上选项 ‘-g’
  • 格式:
gcc -g test.c -o test
gdb test
  • 调试命令
    1、一般先用 l 查看程序,默认显示十行,在输入一次l,显示下一个十行。 l n:命令回到第n行。
    2、设置断点。(用info b可以查看断点设置情况)(del 1 删除第一个断点,del 3 删除第三个断点)
    3、运行到断点,r
    4、查看变量 p
    5、单步运行 n

C语言的高级编程(一)_第2张图片

C语言提高

条件编译

#if 
......
#else
......
#endif
  • 实例
#define _DEBUG_ 1
if _DEBUG_
printf("The macro _DEBUG_ is defined\n");
#else
printf("The macro _DEBUG_ is not defined\n");
#endif

结构体

  • 将不同类型的数据互相联系构成一个整体即是结构体。
struct 结构体名
{
	数据类型	成员名1;
	数据类型 成员名2..
	..
	数据类型 成员名n;
}
  • 特点
    结构体成员名可以与程序中的变量名相同,二者并不代表同一对象。
    1、结构体类型是用户自行构造的
    2、它由若干个不同的基本数据类型的数据构成
    3、它属于C语言的一种数据类型,与整型、实型相当。因此,定义它时不分配空间,只有用它定义变量时才分配空间
    4、一般写到全局变量处,方便整个程序能调用。

  • 举例

第一种方法

//职工信息
struct worker
{
	long number;
	char name[20];
	char sex;
	int age;
	float salary;
	char address[80];
};
int main()
{
	struct worker worker1, worker2;
	return 0;
}

第二种方法,在定义结构体时定义变量

struct worker
{
	long number;
	char name[20];
	char sex;
	int age;
	float salary;
	char address[80];
}worker1, worker2;

第三种方法,不定义结构体名字,直接定义变量

struct
{
	long number;
	char name[20];
	char sex;
	int age;
	float salary;
	char address[80];
}worker1, worker2;
  • 初始化
// 第一种方法
struct 结构体名 变量名 = {初始数据表}//第二种
struct 结构体名
{

}变量名 = {初始数据表}
  • 大小
    一个结构体变量占内存的实际大小,可以用sizeof求出。它的运算表达式为:
    sizeof(struct worker)
    sizeof(worker1)

注意:
1、内存对齐问题!!
2、结构体可以嵌套。
3、在数组中,数组是不能够彼此赋值的,而结构体类型变量可以相互赋值。(前提是:两个是同一结构体类型的结构体变量)

worker2 = worker1 //是正确的
  • 结构体的嵌套
struct birthday{
	int year;
	int month;
	int day;
}
struct
{
	long number;
	char name[20];
	char sex;
	struct birthday age;
	float salary;
	char address[80];
}

  • 结构体数组
    具有相同结构体类型的结构体变量可以组成数组,称它们为结构体数组。结构体数组的每一个结构体院上诉都是结构体类型的数据,它们都分别包括各个成员项。
// 第一种方法
struct student
{
	char name[20];
	char sex;
	int age;
	char addr[20];
};
struct student stu[3];

// 第二种方法
struct student
{
	char name[20];
	char sex;
	int age;
	char addr[20];
}stu[3];

// 第三种方法
struct 
{
	char name[20];
	char sex;
	int age;
	char addr[20];
}stu[3];

结构体指针

可以设定一个指针变量用来指向一个结构体变量。此时该指针变量的值是结构体变量的起始地址,该指针称为结构体指针。
结构体指针和前面介绍的各种指针在特性和方法上是相同的。与前述相同,在程序中结构体指针也是通过“*”来访问他对象

struct 结构体名 * 结构指针名;
//其中结构体名必须是已经定义过的结构体变量

获取结构体成员

//第一种方法
(*p).name
//第二种方法
p->name

共用体

不同数据类型的数据可以使用共同的存储区域,这种数据构造类型称为共用体,又称联合体。共用体在定义、说明和使用形式上与结构体相似。两者本质上的不同仅在于使用内存的方式上。
一般形式为:

union 共用体名
{
	数据类型  成员列表;
}

这里定义一个共用体类型union gy,它由三个成员组成,这三个成员在内存中使用共同的存储空间。由于共用体内各成员的数据长度往往不同,所以共用体变量在存储时总是按其成员中数据长度最长的成员占用内存空间。

union gy
{
	int i;
	char c;
	float f;
}

typedef

typedef <已有数据类型> 	<新数据类型>;

//如下  
typedef int INTEGER
//等价于 int i
INTEGER i;

typedef与结构体相结合

typedef struct _node_
{
	int data;
	struct _node_ *next;    // 自引用要定义成指针变量
} listnode, *linklist

//其中listnode等价于struct _node_, 而linklist等价于struct _node_ *

内存管理

动态内存
  • C/C++定义了4个内存区间:

    • 代码区
    • 全局变量与静态变量区
    • 局部变量区,即栈区
    • 动态存储区,即堆区
  • 静态存储分配
    通常定义变量,编译器在编译时可以根据该变量的类型知道所需的内存空间大小,从而系统在适当的时候为他们分配确定的存储空间。

  • 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束会这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

  • 动态存储分配

    • 有些操作对象要在程序运行时才能确定,系统根据运行时的要求进行内存分配,这种方法称为动态存储分配
    • 动态存储分配都在堆中进行
    • 从堆上分配,亦称动态内存分配。程序在运行的时候使用malloc申请任意多少的内存,程序员自己负责在何时用free释放内存。动态内存的生存期由程序员决定。
  • malloc/free

void * malloc(size_t num)
void free(void *p)

注意:
1、malloc申请到的是一块连续的内存,有时会申请不到内存,返回NULL。
2、malloc返回值的类型是void *,所以在调用malloc时要显式地进行类型转换,将void * 转换成所需要的类型。
3、free释放一块内存中的一部分是不被允许的。
4、删除一个指针,(free§)实际意思是删除了p所指向的目标,释放堆空间后,p成了空悬指针。

举例:
C语言的高级编程(一)_第3张图片
例子2:编写获取一个字符串的函数
C语言的高级编程(一)_第4张图片

你可能感兴趣的:(Linux)