千家信息网

C语言的指针详细介绍

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇文章主要讲解了"C语言的指针详细介绍",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"C语言的指针详细介绍"吧!C语言的指针C语言最臭名昭著的是就是其
千家信息网最后更新 2026年10月31日C语言的指针详细介绍

这篇文章主要讲解了"C语言的指针详细介绍",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"C语言的指针详细介绍"吧!

C语言的指针

C语言最臭名昭著的是就是其指针的使用,也是C语言的精华所在。很多人在学习C语言时,吐槽指针特别难以学习和使用。今天我们来探讨一下C语言指针的问题。

指针的引入

C语言一个特点就是一切皆内存,定义任何类型的变量,都要分配内存。在函数里定义变量,需要在栈内存上非配;定义全局变量,需要在静态内存区分配内存,就连定义函数,也要在静态区分配内存(这就是所谓的代码段存储区域);不固定大小的内存,需要在动态区分配内存。

有了内存,就需要操作内存,也就是读取或者写入内存数据。C语言的最简单的内存操作就是通过赋值操作符(=)实现。比如下面的代码,赋值给变量a,实际就是改变a变量占用的内存的数据; 甚至是用户自定义的结构体变量c,也可以直接使用赋值运算符将b占用的内存块的数据拷贝到c占用的内存块,来完成内存的读写操作。之

int a;a = 6;strcut a_t{   int m_a;   char m_b;   shor m_c;};struct a_t b;a.m_a = 1;a.m_b = 2;a.m_c = 3;struct a_t c;//使用赋值运算符,将b里面所有成员的值赋给c里面的成员,即完成内存拷贝操作。c = b;

所以可以这样操作,是因为C语言的变量包含内存的地址(通过&取)和内存大小(通过sizeof取),知道这两个信息,即使没有赋值运算符,也可以使用memcpy实现赋值的功能。比如下面的代码,完全可以不使用赋值运算符,但实现了赋值的目的。

#include static int g_test = 0;int main(){    int a = 1;    //这里我们使用memcpy操作内存,实现赋值的操作    memcpy(&g_test, &a, sizeof(a));        return 0;}

但是这里有一个问题,即使C语言的函数参数传递只有值传递,就是说所有的变量通过参数传递,都会产生一份拷贝,唯一的办法就是传递变量的地址,这就产生的了用一个专门的类型来存储变量的内存地址的需求,指针应运而生了,这样做有下面的好处:

  • 用一个专门的类型保存内存地址,比用现有类型(int, unsigned int)更方便,因为指针确定了内存地址的大小。

  • 引入语法,为了方便操作内存:像上面的操作一个语句就可以解决了int *addr = &g_test; *addr = 1;这个可能还不太明显,但是到了结构体有很多成员变量,我们就要自己算每个成员的偏移量了,而指针可以直接找到每个成员的地址, 如指针的->符号操作,也可以使用[]进行内存的偏移操作。

二级指针

C语言引入了指针,又衍生出个二级指针的概念,直接弄晕了一部分新生,其实二级指针只是语法的体现,本质上也是指针,是用来存储内存地址的,这个本质没有变化。比如:

int a = 0;//p1存储a的地址int *p1 = &a;//p2存储p1的地址int **p2 = &p;

C语言的所有变量都是内存,都可以取地址,指针变量也不例外。不管是几级指针,都可以当做一级指针使用, 只要自己知道当前变量的意义然后处理好就可以了,比如下面的代码:

int alloc_mem(char *p, int size){    char *tmp_p = (char *)malloc(size);    //*p存储的是`p1`或者`p2`变量的内存地址,用memcpy直接将分配的内存地址付给到p指向的内存    memcpy(p, &tmp_p, sizeof(char *));        return 0;}int alloc_mem1(char **p, int size){    *p = (char *)malloc(size);            return 0;}int main(){    char *p1 = NULL;    char *p2 = NULL;        //利用c语言的强转    alloc_mem((char *)&p1, 2);        //利用二级指针    alloc_mem1(&p2, 2);}

上面的alloc_mem和alloc_mem1效果是一样的,只不过alloc_mem1使用的二级指针的概念。

指针与数组

指针与数组有者本质的区别,指针用来存储一块内存的地址,严格的来说是一块内存的起始地址,至于这块内存有多大,是不知道的,必须使用者显式的指定。比如memcpy这个函数,原型如下:

void *memcpy(void *dst, const void *src, size_t n);

dst指针指的是目标内存的起始地址,但是其指向的内存到底有多大,必须由参数n来给出,负责函数无法知道是否溢出了。而数组本身就是一块内存,包括数组的起始地址和大小,比如我们定义一个数组:

//该数组的起始地址为&arr,大小为sizeof(arr)int arr[32];

arr数组的地址为&a,数组的大小为sizeof(arr)。这里就产生一个问题,就是如何通过函数参数传递数组,C语言是不支持传递数组的,它会默认把数组转换为数组的起始地址的指针。所以C语言函数传递数组,需要额外带上数组的大小,以防止内存溢出的问题。实际上,只要传递指针参数给函数,都要带上这个指针指向内存的大小。

指针难学?

大部分人都认为指针难学,其实不在指针本身,而是指针指向的内容--内存。C语言要保存数据,可以在栈上分配,这部分内存的作用域仅限于函数内部;可以在静态区分配内存,这个区域的内存作用域是全局的,但仅限于确定大小的内存;可以在动态区分配内存,这部分的内存作用域是全局的,支持可变大小的内存。C语言程序存储数据的大部分内存都是在动态区分配的。这就产生了内存管理问题,包括单不限于:

  • 内存的分配

  • 内存的释放

  • 内存大小的检查

  • 内存分配失败的处理

  • 边界的处理:字符总是以0结尾

  • 读越界的处理:在有效内存之外读数据

  • 写越界的处理:在有效内存之外写数据

由于以上问题的存在,导致C语言不像java,python那样使用起来方便,因为这些语言都有垃圾回收器,不用使用者处理关于内存的问题。这才是C语言难学的根本。

结论
  • 指针是存储内存地址的数据类型,C语言可以根据内存地址操作内存。

  • 指针和数组不相同,指针存储的是内存的起始地址,不包括内存的大小;数组既有起始地址,也有大小。

  • 通过函数传递指针,除了指针参数本身,还要带上指针指向内存的大小。

  • 指针难学并非指针本身,而是内存管理难处理

感谢各位的阅读,以上就是"C语言的指针详细介绍"的内容了,经过本文的学习后,相信大家对C语言的指针详细介绍这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

内存 指针 语言 地址 数组 变量 大小 分配 函数 就是 存储 数据 问题 处理 起始 参数 面的 成员 指向 类型 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 工业互联网科技新基建 互联网科技公司电话 贷财互联网科技 互联网科技股有哪些 新华互联网科技校企合作 顺网科技2021年互联网排名 宁夏众和广鑫互联网科技有限公司 互联网科技公司有风险吗 阿大互联网科技有限公司 江阴互联网智能科技产品进口 互联网新科技动漫ppt素材 伍佰万互联网科技怎么赚钱 互联网科技资金流入 下一代互联网重大应用科技园 互联网科技机房 万物互联网智能科技 张家口科技产业互联网平台 唐山双旺合互联网科技产业园 互联网科技大佬云集 互联网企业和网络科技有限公司 猪兼强互联网科技 成都狮子座互联网科技 无锡溥仪互联网科技有限公司 成都仁贤领冠互联网科技有限公司 深圳国际航运科技和互联网 互联网系的金融科技公司 互联网科技教育视频 湖南一路畅行互联网科技 烟台灵鸽互联网科技有限公司 信承诺互联网科技有限公司
0