一、复合类型(自定义类型)
1.1 共用体(联合体)
-
共用体和结构体区别
-
存储方式:
-
结构体:结构体中的每个成员都占据独立的内存空间,成员之间按照定义的顺序依次存储
-
共用体:共用体中的所有成员共享同一块内存空间,不同成员可以存储在同一个地址上
-
-
内存占用:
-
结构体:结构体的内存占用是成员变量占用空间之和,每个成员变量都有自己的内存地址
-
共用体:共用体的内存占用是最大成员变量所占用的空间大小,不同成员变量共享同一块内存地址
所谓的大端模式,是指数据的低位(就是权值较小的后面那几位)保存在内存的高地址中,而数据的高位,保存在内存的低地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放; 所谓的小端模式,是指数据的低位保存在内存的低地址中,而数 据的高位保存在内存的高地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。 1)大端模式: 低地址 -----------------> 高地址 0x12 | 0x34 | 0x56 | 0x78 2)小端模式: 低地址 ------------------> 高地址 0x78 | 0x56 | 0x34 | 0x12
-
-
#include <stdio.h> #include <string.h> union un { char ch; int s; /* data */ }un; int main() { un.s = 0x12345678; printf("%p\n", un.ch); if (un.ch == 0x78) { printf("小端对齐\n"); } else { printf("大端对齐\n"); } return 0; }
1.2 枚举
-
枚举:将变量的值一一列举出来,变量的值只限于列举出来的值的范围内
-
语法格式:
enum 枚举名 { 枚举值表 };
-
-
在枚举值表中应列出所有可用值,也称为枚举元素
-
枚举值是常量,不能在程序中用赋值语句再对它赋值
-
枚举元素本身由系统定义了一个表示序号的数值从0开始顺序定义为0,1,2 …
-
-
1.3 typedef
-
typedef为C语言的关键字,作用是为一种数据类型(基本类型或自定义数据类型)定义一个新名字,不能创建新类型。
二、内存管理
2.1 C代码编译过程
-
预处理
-
-
宏定义展开、头文件展开、条件编译,这里并不会检查语法
-
-
编译
-
-
检查语法,将预处理后文件编译生成汇编文件
-
-
汇编
-
-
将汇编文件生成目标文件(二进制文件)
-
-
链接
-
-
将目标文件链接为可执行程序
gcc -E hello.c -o hello.i //处理文件包含,宏和注释 gcc -S hello.i -o hello.s //编译为汇编文件 gcc -c hello.s -o hello.o //经汇编后为二进制的机器指令 gcc hello.o -o hello //链接所用的到库 1 预处理:预处理相当于根据预处理命令组装成新的 C 程序,不过常以 i 为扩展 名。 2 编 译:将得到的 i 文件翻译成汇编代码 .s 文件。 3 汇 编:将汇编文件翻译成机器指令,并打包成可重定位目标程序的 O 文件。 该文件是二进制文件,字节编码是机器指令。 4 链 接:将引用的其他 O 文件并入到我们程序所在的 o 文件中,处理得到最终 的可执行文件
-
2.2 进程的内存分布
-
程序运行起来(没有结束前)就是一个进程
-
对于一个C语言程序而言,内存空间主要由五个部分组成 代码区(text)、数据区(data)、未初始化数据区(bss),堆(heap) 和 栈(stack) 组成
-
-
有些人直接把data和bss合起来叫做静态区或全局区
-
-
代码区(text segment)
-
-
加载的是可执行文件代码段,所有的可执行代码都加载到代码区,这块内存是不可以在运行期间修改的。
-
-
未初始化数据区(BSS)
-
-
加载的是可执行文件BSS段,位置可以分开亦可以紧靠数据段,存储于数据段的数据(全局未初始化,静态未初始化数据)的生存周期为整个程序运行过程。
-
-
全局初始化数据区/静态数据区(data segment)
-
-
加载的是可执行文件数据段,存储于数据段(全局初始化,静态初始化数据,文字常量(只读))的数据的生存周期为整个程序运行过程。
-
-
栈区(stack)
-
-
栈是一种先进后出的内存结构,由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。在程序运行过程中实时加载和释放,因此,局部变量的生存周期为申请到释放该段栈空间。
-
-
堆区(heap)
-
-
堆是一个大容器,它的容量要远远大于栈,但没有栈那样先进后出的顺序。用于动态内存分配。堆在内存中位于BSS区和栈区之间。一般由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。
-
2.3 堆区内存的使用
2.4 内存分布代码分析
2.4.1 返回栈区地址
address of stack memory associated with local variable 'a' returned [-Wreturn-stack-address] 这个警告意味着你的代码中有一个函数返回了指向本地变量的地址,而本地变量通常是分配在栈上的。这样做可能会导致未定义的行为,因为在函数调用结束后,本地变量的内存空间将被释放,指向它们的指针就会变成无效。 要解决这个警告,你需要确保函数返回的指针不指向本地变量,或者在函数内部动态分配内存,并返回分配的内存地址。如果你需要返回本地变量的值,可以通过函数参数传递给调用者,而不是返回指向本地变量的指针。
2.4.2 返回data区地址
-
在函数内部使用static修饰的变量称为静态局部变量
-
它在程序运行期间只被初始化一次,并且在函数调用结束后也不会被销毁
2.4.3 返回堆区地址