C语言学习(指针)
May 15. 2026

AI文摘
此内容由AI根据文章内容自动生成.
加载中。

指针

  • 指针是变量的引用,指针变量保存的是变量的地址。

注意事项

  • 数组名为首元素地址,我们可以将其看作一个指针,但该指针值是一个常量,不能修改,所以给数组名自增/自减或赋值都是不允许的。
  • 利用指针变量间接访问内存数据,指针变量能访问多大的内存空间,取决于指针变量的类型
  • static int 无法直接用变量/运行时表达式初始化,是因为静态变量的初始化必须在编译时完成,而变量、函数结果等属于「运行时才能确定」的值,无法满足「编译时常量」的要求。但可以通过「先声明静态变量,再在运行时赋值」的方式,间接实现用变量值初始化静态变量的效果。

指针类型

常量指针

  • const int *p;
  • 数据无法修改,但指针可以修改。
  • 常量数据需要再定义静态变量时初始化,不能用变量初始化。

指针常量

  • int *const p;
  • 指针可以修改,但数据无法修改。
  • 指针常量定义时,必须初始化。

数组指针

  • int (*p)[N];
  • 数组指针是指向数组的指针。
  • 数组指针往往是用于接收二维数组地址的,并且可以间接访问二维数组中的数据。

指针数组

  • 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 void *src, size_t n
  • memmove()函数将内存块复制到另一个内存块,但允许内存块重叠。 参数:void *dest, const void *src, size_t n
  • memcmp()函数比较内存块。 参数:const void *ptr1, const void *ptr2, size_t n

结构体

  • 使用 typedef 定义结构体,使用时不需要在写 struct
  • 结构体指针 *p = &s; p->name = “新名字”;
  • 结构体总大小:必须是最大成员类型大小的整数倍。
  • offsetof 获取成员偏移量

数组成员定义

结构体成员核心特点与初始化方式优缺点及注意事项
定长字符数组
char name[20];
最推荐、最安全。
1. 初始化:声明时可用 {..., "鼠标"} 直接赋值。
2. 修改值:必须用 strcpy(p.name, "新名字");
优点:内存自动管理,不易出错,适合绝大多数场景。
缺点:长度固定,无法存储超过数组长度的字符串。
字符指针
char *name;
灵活但需谨慎。
1. 初始化:声明时可用 {..., "鼠标"} 指向常量。
2. 修改值:可直接用 p.name = "新名字"; 改变指向。
优点:赋值极其方便,节省空间。
致命坑:指向常量字符串时绝对不可修改内容(否则程序崩溃);若要接收用户输入,必须先手动 malloc 分配内存。
柔性数组成员
char name[];
高级用法(不推荐新手)。
1. 初始化:不能使用普通的静态变量和花括号初始化。
2. 使用:必须配合 malloc(sizeof(struct) + 长度) 动态分配。
优点:内存连续,适合处理不定长数据且追求极致性能的场景。
缺点:用法复杂,极易踩到内存越界或管理的坑。

联合体

  • 联合体成员共用同一块内存,只能同时保存一个成员变量的值,按不同类型解释。
  • 联合体大小为最大成员变量大小。

区别:

对比structunion
内存各成员独立共享内存
大小成员总和(含对齐)最大成员大小
成员能否同时使用可以不可以
作用描述对象节省内存

大小端

  • 大小端 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
  • 枚举成员可以值相同,枚举成员不能重复定义名字,枚举成员是常量
对比enum#define
类型有类型无类型
调试更方便不方便
可读性一般
本质整数常量文本替换
> comment on / twitter
>
CC BY-NC-SA 4.0 2021-PRESENT © RYANUO