云计算百科
云计算领域专业知识百科平台

c语言 typedef、共用体、位运算、位段、枚举类型、内存管理

目录

  • 一、typedef
    • 1.1 声明整型
    • 1.2 声明结构体类型
    • 1.3 声明数组
    • 1.4 声明指针
    • 1.5 声明数组指针
    • 1.6 声明函数指针
    • 1.7 声明枚举类型
  • 二、共用体
    • 2.1 共用体的定义
    • 2.2 共用体 vs 结构体
    • 2.3 使用示例
    • 2.4 典型应用场景
    • 2.5 与结构体嵌套使用
    • 2.6 总结
  • 三、位运算
    • 3.1 按位与 &
    • 3.2 按位或 |
    • 3.3 异或 ^
    • 3.4 取反运算符 ~
    • 3.5 左移运算符 <<
    • 3.6 右移运算符 >>
    • 3.7 赋值运算符
  • 四、 位段
  • 五、枚举类型
    • 5.1 基本语法
    • 5.2 枚举常量的值
    • 5.3 定义枚举变量
      • 5.3.1 先定义类型,再声明变量
      • 5.3.2 定义类型的同时声明变量
      • 5.3.3 匿名枚举(不推荐,除非只用一次)
    • 5.4 使用 typedef 简化
    • 5.5 枚举的本质
    • 5.6 典型应用场景
      • 5.6.1 状态机
      • 5.6.2 选项/模式选择
      • 5.6.3 错误码
    • 5.7 注意事项
    • 5.8 实用技巧:将枚举值转为字符串
    • 5.9 与 #define 对比
    • 5.10 总结
  • 六、内存管理
    • 6.1 存储模型
    • 6.2 动态内存

一、typedef

在 C 语言中,typedef 是一个关键字,用于为已存在的数据类型创建一个新的别名。它不会创建新类型,只是让代码更简洁、可读性更强,尤其在处理复杂类型(如结构体、函数指针、数组指针等)时非常有用。

当不同源文件中用到同一类型数据时,常用typedef声明一些数据类型,把它们单独放在一个文件中,然后在需要用到它们的文件中用 #include 命令把他们包含进来。

使用typedef 有利于程序的通用与移植

typedef 与 #define有相似之处,例如:typedef int COUNT; #define COUNT int; 的作用都是用COUNT 代替int.但是,它们二者是不同的

#define 是在预编译时处理的,它只能作简单的字符串替换,而typedef是在编译时处理的。实际上它并不是作简单的字符串替换,而是采用如同定义变量的方法来声明一个类型

基本语法 typedef 已有的数据类型 新类型名称;

1.1 声明整型

声明 INTEGER 为 整型:

#include <stdio.h>
#include <stdlib.h>

typedef int INTEGER;

int main(){
// INTEGER i=1; 等价于 int i=1;
INTEGER i = 1;
int j = 2;
printf("%d,%d,%d\\n", i, j, i+j);

return 0;
}

1.2 声明结构体类型

声明 date_one 为 DATE 结构体类型

#include <stdio.h>
#include <stdlib.h>

// 定义了一个名为 DATE 的结构体类型
typedef struct{
int month;
int day;
int year;
}DATE;

int main(){
// 声明了一个 DATE 类型的变量 date_one;
DATE date_one;

date_one.month = 9;
date_one.day = 30;
date_one.year = 2025;

printf("%d-%02d-%02d\\n",
date_one.year, date_one.month, date_one.day);

return 0;
}

1.3 声明数组

声明 NUM 为 整型数组类型

#include <stdio.h>
#include <stdlib.h>

// 使用 typedef 为 int[100] 定义了一个新的类型名 NUM
typedef int NUM[100];

int main(){
NUM a = {0};// 等价于 int a[100];
printf("%d\\n", sizeof(a)); // 400

return 0;
}

1.4 声明指针

声明 SRTING 为 字符指针类型

#include <stdio.h>
#include <stdlib.h>

typedef char* SRTING;

int main(){
SRTING a, b;// 等价于 char *a, *b;

a = "Zhangsan";
b = "Lisi";

printf("%d, %d\\n", sizeof(a), sizeof(b)); // 8, 8
printf("%s, %s\\n", a, b); // Zhangsan, Lisi

return 0;
}

1.5 声明数组指针

声明 POINT 为 指向数组的指针类型(数组指针)

#include <stdio.h>
#include <stdlib.h>

// 定义了一个 指向数组的指针类型
// 指向一个包含 3个int的数组 的指针
typedef int (*POINT)[3];

int main(){
POINT p1; // 等价于 int (*p1)[3];
int arr1[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
p1 = arr1;

printf("%d, %d, %d\\n", p1[0][0], p1[1][1], p1[2][2]);

return 0;
}

1.6 声明函数指针

声明 POINT 为 指向函数的指针类型(函数指针),该函数返回整型值

#include <stdio.h>
#include <stdlib.h>

// 定义了一个 函数指针类型, POINT 是一个类型别名
typedef int (*POINT)(void);// 明确:无参, 返回 int

int fun(void){
printf("nian is very handsome\\n");
return 0;
}

int main(){
// POINT p1; 等价于 int (*p1)();
POINT p1;

p1 = fun;
(void)p1();// 显式忽略返回值

return 0;
}

1.7 声明枚举类型

声明 Bool 为 枚举类型

typedef enum {
FALSE,
TRUE
}Bool;

// 使用
Bool flag = TRUE;

二、共用体

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

2.1 共用体的定义

union 共用体名 {
成员列表;
};

示例:

#include <stdio.h>

union data {
int i;
float f;
char str[20];
};

这个 union data 中的三个成员 i、f 和 str 共享同一段内存,其大小等于最大成员所需的内存 (这里是 char[20],所以通常是 20 字节)。

2.2 共用体 vs 结构体

特性struct(结构体)union(共用体)
内存分配 每个成员独立存储,总大小 ≥ 各成员之和(考虑对齐) 所有成员共享同一块内存,总大小 = 最大成员的大小
赋值影响 修改一个成员不影响其他成员 修改一个成员会覆盖其他成员的值
用途 存储多个相关数据 在同一内存位置存储不同类型的数据(节省空间、类型转换等)

2.3 使用示例

注意:任何时候,只能安全地读取最近写入的那个成员。读取其他成员会导致未定义行为或垃圾值。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

union data{
int i;
float f;
char str[20];
};

int main(){
union data d1;

d1.i = 10;
printf("data.i:%d\\n", d1.i);

d1.f = 20;
printf("data.f:%.2f\\n", d1.f);

strcpy(d1.str, "Zhangsan");
printf("data.str:%s\\n", d1.str);

// 共用体的大小 输出通常是 20 (因为 char str[20] 是最大成员)
printf("Size of union Data: %zu\\n", sizeof(d1));

return 0;
}

2.4 典型应用场景

1、节省内存 当多个变量不会同时使用时,可用共用体共享内存。

2、类型双关 用于在不同数据类型之间“重新解释”同一块内存(需谨慎!)。

union {
unsigned int i;
float f;
} converter;

converter.f = 3.14f;
printf("As integer: 0x%x\\n", converter.i); // 查看 float 的二进制表示

3、协议解析 / 硬件寄存器访问 例如解析网络数据包或访问硬件寄存器的不同字段。

union Register {
uint32_t raw;
struct {
uint32_t enable : 1;
uint32_t mode : 3;
uint32_t value : 28;
} bits;
};

2.5 与结构体嵌套使用

struct Packet {
int type;
union {
int int_data;
float float_data;
char msg[32];
} payload;
};

根据 type 字段决定读取 payload 中的哪个成员 —— 这是实现“变体记录”的常用方式。

2.6 总结

  • 共用体 = 多个成员共享同一内存
  • 大小 = 最大成员的大小(考虑对齐)
  • 任何时候只能安全使用最后一个写入的成员
  • 用途:节省内存、底层数据操作、协议解析、硬件编程等
  • 风险:误读未写入的成员 → 垃圾值或未定义行为

提示:C11 引入了 _Generic 和更安全的类型处理,但在资源受限环境(如嵌入式),union 仍是不可或缺的工具。

三、位运算

运算符功能说明举例
~ 位逻辑反 ~a
& 位逻辑与 a&b
I 位逻辑或 a I b
^ 位逻辑异或(相同为假,不同为真) a^b
>> 右移动 a>>b
<< 左移动 a<<b

3.1 按位与 &

3 & 5 并不等于 8 , 应该是按位与运算: 0000 0011 (3) 0000 0101 (5) 一一一一一一一 0000 0001 (1)

两个相应的二进制中两个都为1,该位的结果值为1 与0运算都为0,与1运算为本身

如果参加 & 运算的是负数,如(-3 & -5),则要以补码形式表示为二进制数,然后再按位进行 “与运算”。

按位与 & 运算的用途 1、清零 若相对一个存储单元清零,即使其全部二进制位为0,只要找一个二进制数,其中各个位符合以下条件: 原来的数中为1的位,新数中相应位为0,然后使二者进行 & 运算,即可达到清零目的。

例如: 要求将二进制数 1110 0101 的第二位清零

1110 0101 1111 1011 一一一一一一一 1110 0001

2、取一个数中某些指定位 例如: 我们需要对一个字符数据取出其低八位的值时,我们可以这么做。

11010101 01011011 00000000 11111111 一一一一一一一一一一 00000000 01011011

3.2 按位或 |

两个相应的二进制中只要有一个为1,该位的结果值为 1 即:

0 | 0 = 0 ,0 | 1 =1 1 | 0 = 1,1 | 1 = 1

例如:

0011 0000 0000 1111 一一一一一 0011 1111

编写一个程序,将输入的大写字母转换为小写字母,输入的小写字母转换为大写字母,要求用位操作完成转换过程 A ASCII : 65 对应二进制为 -> 0100 0001 a ASCII : 97 对应二进制为 -> 0110 0001

#include <stdio.h>
#include <stdlib.h>

int main(){
char ch;
printf("Please enter a letter:");
ch = getchar();
while(!((ch>='A' && ch<='Z') || (ch>='a' && ch<='z'))){
printf("Input error, please re-enter:");
ch = getchar();
}
if(ch & 32){ // 0010 0000 判断是否为小写(非零表示小写)
ch = ch & 223; // 1101 1111 清除第 5 位,转大写
}
else{
ch = ch | 32; // 0010 0000 设置第 5 位,转小写
}
putchar(ch);

ch = getchar();
putchar(ch);

return 0;
}

3.3 异或 ^

与 0 异或保留原值,与 1 异或取反 异或运算符 ^ 也称 XOR运算符 它的规则是:若参加运算的是两个二进制位同号则结果为0(假), 异号则为1(真)

即: 0 ^ 0 = 0, 0 ^ 1 = 1 1 ^ 0 = 1, 1 ^ 1 = 0

例如:

0011 1001 0010 1010 一一一一一 0001 0011

1、使特定位翻转 设有 0111 1010,想使其低四位翻转,即 1 变为0 ,0 变成1。可以将它与 0000 1111 进行 ^ 运算,即(翻转位与 1 异或取反):

0111 1010 0000 1111 一一一一一 0111 0101

2、与 0 异或 ^ ,保留原值 例如:

0000 1010 0000 0000 一一一一一 0000 1010

因为原数中的1 与 0 进行 ^运算得1, 0 ^ 0 得0,故保留原数。

3、交换两个值,不用临时变量 例如: a=3,b = 4 ,现在想要将 a,b 变量的值交换位置 a = a ^ b; b = b ^ a; a = a ^ b; 这种方法也常用于加密算法

3.4 取反运算符 ~

~ 是一个单目运算符,用来对一个二进制数按位取反,即将 0 变成1,将1变成0; 例如:~ 025 是对八进制数 25 (二进制 0001 0101)按位取反

0001 0101 一一一一一 1110 1010

3.5 左移运算符 <<

左移运算符是用来将一个数的各二进制位全部左移若干位。

例如: a = << 2 将a的二进制数左移2 位,右边补0. 若 a = 15, 即二进制数 0000 1111,左移2位得, 0011 1100(十进制数60)。 若高位左移后溢出,舍弃。

左移n位相当于该数乘以2^n

左移1位相当于该数乘以2,左移2位相当于该数乘以4,15<<2 = 60,即乘了4 (2的2次方) 但此结论只适用于该数左移时被溢出舍弃的高位中不包含1的情况。

假设一个字节(8)位存一个整数,若a为无符号整型变量,则a = 64时,左移1位时溢出的是0,而左移2位时,溢出的高位中包含1。

64原:0100 0000 左移1位:0100 0000 左移2位:0000 0000

3.6 右移运算符 >>

右移运算符是a >>2表示将a的各二进制位右移2位,移到右端的低位被舍弃,对无符号数,高位补0。

例如: a = 017时, a的值用二进制形式表示为 0000 1111,舍弃低2位11,得到:a>>2 == 0000 0011

右移一位相当于除以2 右移n位相当于除于2^n

右移移动,需要注意符号位问题: 1、对无符号数,右移时左边高位移入0;

2、对于有符号的值,如果原来符号位为0 (该数为正),则左边也是移入0 如果符号位原来位1(即负号),则左边移入0还是1,要取决于所用的计算机系统。有的系统移入0,有的系统移入1。 移入0的称为 “逻辑右移”,即简单右移;移入1的称为“算术右移”。

例: a 的值是十进制数 -2; a == 1111 1110(二进制) 无符号数:a>>1 :0111 1111(逻辑右移) 有符号数:a>>1 :1111 1111(算术右移)

#include <stdio.h>
#include <stdlib.h>

void main()
{
unsigned char a = 2;// 1111 1110
a = a>>1;
printf("%d\\n",a); // 0111 1111 (127)
}

#include <stdio.h>
#include <stdlib.h>

void main()
{
char a = 2;// 1111 1110
a = a>>1;
printf("%d\\n",a); // 1111 1111 (-1)
}

3.7 赋值运算符

位运算符与赋值运算符可以组成复合赋值运算符。

例如: &= , |= , >>= , <<= , ^ =

a &= b 相当于 a = a & b a <<= 2 相当于 a = a << 2

例1:取一个 char a 从右端开始的 2-5位: ①先使a 右移 2位 : a>>2 目的是使要取出的那几位移到最右端 ②设置一个低四位全为1,其余全为0的数。 ~ (~0 << 4) // 0000 1111 ③将上面 ① ②进行 &运算 (a >> 2) & (~ 0 <<4 )

#include <stdio.h>
#include <stdlib.h>

void main()
{
char a, b, c, d;
printf("Please enter the array to be validated:");
scanf("%d", &a);
b = a>>2;
c = ~(~0 << 4); // ~(1111 1111 << 4) == 0000 1111
d = b & c;
printf("%d\\n", d);
// 输入23 0001 0111 右移2位 0000 0101 结果 5
}

例2:要求将 a 进行右循环移位 在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>

void main()
{
unsigned char a, b, c, d;
int n;
printf("Please enter the number to achieve circular right shift:\\n");
scanf("%d", &a);
printf("Please input the number of bits to be shifted right:\\n");
scanf("%d", &n);

b = a<<(sizeof(char)*8 n); // 取出a的最后n位,左移到最前面,右边补0
c = a>>n;// a右移n位, 左边补0
d = b | c;// 实现右循环移位
printf("%d\\n", d);
// 23 3 226
}

四、 位段

信息的存取一般以字节位单位,实际上,有时存储一个信息不必用一个或多个字节。

例如:“真”或 “假”用0或1表示,只需 1 位即可。

在计算机用于过程控制,参数检测或数据通信领域时,控制信息往往只占一个字节中的一个或几个二进制位,常常在一个字节中放几个信息。

C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为"位段 "或称"位域 ",利用位段能够用较少的位数存储数据。

内存布局(以 GCC / Clang on x86-64 为例)

struct packed{
unsigned a:2; // 占 bit0~bit1
unsigned b:6; // 占 bit2~bit7 → 与 a 共享第 1 个字节
unsigned c:4; // 占 bit0~bit3(新字节开始?不一定!)
unsigned d:4; // 占 bit4~bit7 → 与 c 共享第 2 个字节
int i; // 4 字节, 通常从 4 字节对齐地址开始
}data;

内存布局(小端,GCC 默认):

字节偏移位(7 … 0)成员
0 b[5:0] a[1:0] a(2位), b(6位)
1 d[3:0] c[3:0] c(4位), d(4位)
2 (填充)
3 (填充)
4~7 i(4字节整数) int i

所以: 第一个字节:低2位是 a,高6位是 b 第二个字节:低4位是 c,高4位是 d

1、位段成员的类型必须指定为 unsigned 或 int类型。 2、若某一位段要从另一个字开始存放,可用以下形式定义:

unsigned a:1;
unsigned b:2; 一个存储单元
unsigned :0;
unsigned c:3; 另一存储单元

a、b、c 应连续存放在一个存储单元中,由于用了长度为0的位段,其作用是使下一个位段从下一个存储单元开始存放。因此,只将 a、b 存储在一个存储单元中,c 另存在下一个单元(存储单元可能是一个字节,也可能是两个字节,视不同的编译系统而异)。

3、一个位段必须存储在同一存储单元中,不能跨两个单元。如果第一个单元空间不能容纳下一个位段,则该空间不用,而从下一个单元起存放该位段。 4、可以定义无名位段。 5、位段的长度不能大于存储单元的长度,也不能定义位段数组。 6、位段可以用整型格式符输出。 7、位段可以在数值表达式中引用,它会被系统自动地转换成整型数。

五、枚举类型

在 C 语言中,枚举类型 是一种用户自定义的数据类型,用于定义一组命名的整型常量。它让代码更具可读性、可维护性和安全性。

5.1 基本语法

enum 枚举名 {
枚举常量1,
枚举常量2,
枚举常量3,
...
};

示例:

#include <stdio.h>

enum Color {
RED,
GREEN,
BLUE
};

int main() {
enum Color a = RED;
enum Color b = GREEN;
enum Color c = BLUE;
printf("RED = %d\\n", a); // 输出: RED = 0
printf("GREEN = %d\\n", b); // 输出: GREEN = 1
printf("BLUE = %d\\n", c); // 输出: BLUE = 2
return 0;
}

5.2 枚举常量的值

1、默认从 0 开始,依次递增 1。 2、可以显式指定值,后续未指定的常量从该值继续递增。 示例:

enum Status {
OFF = 0, // 0
ON, // 1(自动 = 0 + 1)
PENDING = 5, // 5
ERROR // 6(自动 = 5 + 1)
};

OFF=0, ON=1, PENDING=5, ERROR=6

5.3 定义枚举变量

有三种方式:

5.3.1 先定义类型,再声明变量

enum Week{
MON,
TUE,
WED
};
enum Week today = TUE;

5.3.2 定义类型的同时声明变量

enum Week{
MON,
TUE,
WED
}today, tomorrow;

5.3.3 匿名枚举(不推荐,除非只用一次)

enum{
MON,
TUE,
WED
}day = MON;

5.4 使用 typedef 简化

避免每次写 enum Name,可用 typedef 创建别名:

typedef enum {
FALSE,
TRUE
}Bool;

// 使用
Bool flag = TRUE;

这是 C 语言中模拟布尔类型的经典方法(C99 后有 _Bool 和 <stdbool.h>)。

5.5 枚举的本质

1、枚举常量是 int 类型的编译时常量。 2、枚举变量在内存中通常以 int 大小存储(但标准未强制,某些编译器可优化为更小类型)。 3、可以对枚举变量进行整数运算(但不推荐,会破坏类型安全)。 示例(合法但不推荐):

enum Color c = RED;
c = c + 1; // c 变成 GREEN(危险!可能越界)

5.6 典型应用场景

5.6.1 状态机

enum State {
IDLE,
RUNNING,
PAUSED,
STOPPED
};

enum State current = IDLE;

5.6.2 选项/模式选择

enum FileMode {
READ_ONLY,
WRITE_ONLY,
READ_WRITE
};

5.6.3 错误码

enum ErrorCode {
SUCCESS = 0,
FILE_NOT_FOUND = 1,
PERMISSION_DENIED = 2
};

5.7 注意事项

问题说明
不是类型安全 C 的 enum 本质是 int,可以赋任意整数值:enum Color c = 999; ✅(编译通过,但逻辑错误)
不能直接输入/输出名字 printf("%s", RED) ❌ 不行!需要手动映射(见下文技巧)
作用域 C89 中枚举常量是全局作用域,可能冲突;C 没有“枚举类”(像 C++ 的 enum class)

5.8 实用技巧:将枚举值转为字符串

C 语言不支持反射,但可以用宏或数组模拟: 方法:字符串数组映射

#include <stdio.h>

enum Color{
RED,
GREEN,
BLUE,
COLOR_MAX
};

const char *color_names[] = {"RED", "GREEN", "BLUE"};

int main() {
enum Color c = GREEN;
printf("Color: %s\\n", color_names[c]); // 输出: Color: GREEN
return 0;
}

要求枚举从 0 开始且连续!

5.9 与 #define 对比

特性enum#define
类型检查 有一定(仍是 int) 无(纯文本替换)
调试支持 调试器可显示名字 只能看到数字
作用域 遵循 C 作用域规则 全局宏,易冲突
自动生成值 支持(默认 0,1,2…) 需手动写
内存 不占用(编译期常量) 不占用

优先使用 enum 而不是 #define 来定义相关常量组!

5.10 总结

  • enum 是定义命名整型常量集合的工具。
  • 默认值从 0 开始,可显式赋值。
  • 提高代码可读性,替代“魔法数字”。
  • 本质是 int,不是强类型(C 语言限制)。
  • 配合 typedef 使用更简洁。
  • 适合表示状态、选项、类别等离散值。

最佳实践:

typedef enum{
STATUS_OK = 0,
STATUS_ERROR,
STATUS_TIMEOUT
}Status;

六、内存管理

6.1 存储模型

C和C++定义了四个内存区间:代码区、全局变量和静态变量区、局部变量区即栈区、动态存储区 即堆区

  • 静态存储分配

    • 通常定义变量,编译器在编译时都可以根据该变量的类型知道所需内存空间的大小,从而系统在适当的时候为他们分配确定的存储空间。
    • 在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。
    • 栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
  • 动态内存分配

    • 有些操作对象只有在程序运行时才能确定,这样编译器在编译时无法为他们预定存储空间,只能在程序运行时,系统根据运行时的要求进行内存分配。
    • 所有动态存储分配都在堆区中进行。
    • 从堆上分配,也叫做动态内存分配。程序在运行的时候用 malloc 申请任意多少的内存,程序员自己负责在何时用 free 释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
  • 堆内存的分配 和 释放

    • 当程序运行到需要一个动态分配的 变量 或 对象时,必须向系统申请取得堆中的一块所需大小的存储空间,用于存储该变量或对象。当不再使用该变量或对象时,也就是它的生命结束时,要显式释放他所占用的存储空间,这样系统就能对该堆空间进行再次分配,做到重复使用有限的资源。
    • 堆区是不会自动在分配时做初始化的,所以必须用初始化来显式初始化。

6.2 动态内存

malloc / free

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

  • malloc 函数本身并不识别要申请的内存是什么类型,它只关心内存的总字节数。
  • malloc 申请到的是一块连续的内存,有时可能会比所申请的空间大,其有时会申请不到内存,返回 NULL。
  • malloc 返回值的类型是 void ,所以在调用的时候需要显式的进行类型转化,将void 转化成所需的指针类型。
  • 如果 free 的参数是 null 的话,没有任何效果 释放一块内存中的一部分是不被允许的。

注意事项 1、删除一个指针 p free(p); 实际意思是删除了p所指的目标(变量或对象等),释放了它所指占的堆空间,而不是删除p本身,释放堆空间后,p 成了空悬指针。

2、动态资源分配失败,返回一个空指针(null), 表示发生了异常,堆资源不足,分配失败。

3、 malloc 和 free是配对使用的,free只能释放堆空间。如果malloc返回的指针值丢失,则所分配的堆空间无法回收,称为内存泄漏

同一空间重复释放也是危险的,因为该空间可能已另分配,所以必须妥善保存malloc返回的指针,以保证不发生内存泄漏,也必须保证不好重复释放堆内存空间。

  • 野指针:不是NULL指针,是指向"垃圾"内存的指针,野指针 很危险。
  • 野指针造成的主要原因有两种
    • 指针变量没有初始化
    • 指针变量 p 被 free 之后,没有置为 NULL,让人误以为p是个合法的指针,指针操作超越了变量的使用范围。
赞(0)
未经允许不得转载:网硕互联帮助中心 » c语言 typedef、共用体、位运算、位段、枚举类型、内存管理
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!