静态变量初始化与字符串存储解析
指针
- 指针是变量的引用,指针变量保存的是变量的地址。
注意事项
- 数组名为首元素地址,我们可以将其看作一个指针,但该指针值是一个常量,不能修改,所以给数组名自增/自减或赋值都是不允许的。
- 利用指针变量间接访问内存数据,指针变量能访问多大的内存空间,取决于指针变量的类型
- static int 无法直接用变量/运行时表达式初始化,是因为静态变量的初始化必须在编译时完成,而变量、函数结果等属于「运行时才能确定」的值,无法满足「编译时常量」的要求。但可以通过「先声明静态变量,再在运行时赋值」的方式,间接实现用变量值初始化静态变量的效果。
指针类型
常量指针
- const int *p;
- 数据无法修改,但指针可以修改。
- 常量数据需要再定义静态变量时初始化,不能用变量初始化。
指针常量
- int *const p;
- 指针可以修改,但数据无法修改。
- 指针常量定义时,必须初始化。
数组指针
- int *p;
- 数组指针是指向数组的指针。
- 数组指针往往是用于接收二维数组地址的,并且可以间接访问二维数组中的数据。
指针数组
- int *p[N];
- 指针数组是元素是指针类型的数组。
- 用于数组外排序
字符指针
- char *p;
- 字符指针是指向字符的指针。
- 保存字符串的两种方法:字符指针、字符数组 区别:
- 字符指针保存的是字符串的地址,字符串的内容不能改变。
- 字符数组保存的是字符串的内容,字符串的内容可以改变。
- 创建字符指针时,必须初始化,否则会报错。
- 字符数组其实是保存了字符串常量的一份内存拷贝,而字符指针是直接引用字符串常量本身。
函数指针
- int (*p)(int, int);
- 函数指针是指向函数的指针。
- 函数指针可以作为参数传递给其他函数,也可以作为返回值返回给其他函数。
- 应用场景:回调函数
指针函数
- int *func(int a, int b);
- 指针函数是指向函数的指针。
- 指针函数返回地址,要求函数返回后,该地址上的数据不能被回收。
多级指针
- int **p;
- 多级指针是指向指针的指针。
- 多级指针可以保存多维数组的地址。
- 应用场景:main函数参数,argv参数为多维数组,argv[0]为字符串数组,argv[0][0]为字符。
动态内存管理
- malloc()函数分配内存,返回一个指针,指向分配的内存。 参数:size_t size
- calloc()函数分配内存,返回一个指针,指向分配的连续内存。 参数:size_t nmemb, size_t size
- realloc()函数重新分配内存,返回一个指针,指向重新分配的内存。 参数:void *ptr, size_t size
内存操作
- memset()函数将内存块设置为某个值。 参数:void *ptr, int value, size_t n 常用:内存空间清零
- memcpy()函数将内存块复制到另一个内存块。 参数:void dest, const voidsrc, size_t n
- memmove()函数将内存块复制到另一个内存块,但允许内存块重叠。 参数:void dest, const voidsrc, size_t n
- memcmp()函数比较内存块。 参数:const void ptr1, const voidptr2, size_t n
结构体
- 使用 typedef 定义结构体,使用时不需要在写 struct
- 结构体指针 *p = &s; p->name = “新名字”;
- 结构体总大小:必须是最大成员类型大小的整数倍。
- offsetof 获取成员偏移量
数组成员定义
联合体
- 联合体成员共用同一块内存,只能同时保存一个成员变量的值,按不同类型解释。
- 联合体大小为最大成员变量大小。
区别:
大小端
- 大小端 CPU存储多字节数据时:字节存放顺序不同
- 小端,低位存放在低地址,高字节存放在高地址; 大端,高字节放低地址。
#include <stdio.h>
union Test
{
int a;
char b;
};
int main()
{
union Test t;
t.a = 1;
if (t.b == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
}枚举
- 枚举类型用于定义一组命名的常量。
- typedef 配合 enum
- 枚举成员可以值相同,枚举成员不能重复定义名字,枚举成员是常量