C语言的指针详细介绍

发布时间:2021-08-11 19:01:19 作者:chen
来源:亿速云 阅读:171

这篇文章主要讲解了“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 <stdint.h>
static int g_test = 0;

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

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

二级指针

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_memalloc_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语言程序存储数据的大部分内存都是在动态区分配的。这就产生了内存管理问题,包括单不限于:

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

结论

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

推荐阅读:
  1. C语言指针是什么?C语言指针的概念。
  2. RPC的详细介绍

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c语言

上一篇:C语言中结构体struct怎么对齐

下一篇:C语言和Python哪个比较好

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》