一、什么是指针?
在了解指针之前先要弄清楚地址的概念。
如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。编译统
根据城西中定义的变量类型,分配一定长度的空间。例如:整型变量分配4个字节,字符型分配1个字节,单精度分配4个字节等。内存区的每一个字节有一个编号,这就是“地址编号”,它就相当于旅馆中的房间号,每一个房间都可以看作一块内存区域,都可以用来存放东西,我们给每个房间都编一个房间门牌号,用于更好的区分每一个房间,内存中也是一样的,整个内存由很多个字节组成,每个字节都有其对应的“房间号”,这就是“地址”了。通过这个“房间号”就可以找到其对应的“房间”,然后就可以从房间里取东西,或者把东西放进房间里了。
理解了地址的概念之后,那所谓的指针,就是内存地址,也就是地址的编号,可以把“指针指向地址”理解成“用小本本把房间号记下来”,那这个小本本就相当于一个用于记房间号的指针了,一个变量的地址称为此变量的“指针”。
二、指针常量与指针变量
1、指针常量
之前有了解过不同数据类型的变量所占内存字节数的这个概念,那么系统在编译时给一个变量分的
内存地址就称为此变量的“指针”,这个指针的指向是无法改变的,所以又称为指针常量,数组的地址也是指针常量(也称为地址常量)。如:
1. int a=10; 2. printf(“%p\n”,&a); 3. //'&'是取址符,这里的&a是取变量a的地址,以%p的格式输出地址
2、指针变量
(1)指针变量的概念
如果有一个变量专门用来存放另一个变量的地址,则称这个变量为“指针变量”,也就是说C语言中有一类变量是专门用来存储(指向)地址的,我们将它称为“指针变量”,指针变量的中存储的地址可以被改变,也就是可以改变指针变量的指向,就好比一张纸或一个小本本,写着一个房间的房间号,那把这个房间的房间号擦掉,写上另一个房间的房间号也是可以的,这就是指针变量和指针常量最大的区别所在了,可以改变指针变量的指向。
2)指针变量的定义
定义指针变量的一般格式:
类型名 * 指针变量名;例如:
1. int *p,*q; 2. char *p1,*q1; 3. double *p2,*q2;
注意:左端的int、char等是在定义指针变量时必须指定的“基类型”。指针变量的基类型用来规定此指针变量可以指向的变量的类型。如:上面定义的p和q只能用于指向int整型变量的地址,p2和q2只能用于指向double双精度类型变量的地址。
(3)指针变量的引用
与指针和地址相关运算符:’*’(指针运算符)和’&’(取地址运算符)//区别对待位运算符&
例如:
int a,*p; p=&a;*p=10;
在引用指针变量时,有以下几种情况:
①给指针变量赋值如:
1. int a,*p; p=&a; *p=10; 2. int a = 10,b=20; 3. int *p=&a;//定义一个整型指针变量p,初始化p的值为a的地址,也就是p指向a地址
②解引用:
*p=30; //通过指针变量p引用a变量,改变a的值为30 //这里的’*’为解引用符号,p引用指针变量p所指向地址中对应的值 scanf(“%d”,p); //scanf通过指针变量p给变量a赋值 printf(“%d\n”,*p); //通过指针变量p输出变量a的值 *p=b; //将b的值放入指针变量p所指向的内存地址中(a的地址单元中) p=&b; //改变指针p的指向,指针p不再指向a的地址了,而是指向b的地址 printf(“%d\n”,*p); //输出变量b的值
③输出内存地址编号
printf(“%p\n”,p); //以十六进制的格式输出指针变量p所指向地址的内存地址编号 printf(“%d\n”,&a); //以十进制的格式输出变量a所在的内存地址编号 printf(“%o\n”,&b); //以八进制的格式输出变量b所在的内存地址编号 printf(“%p\n”,&p); //以十六进制的格式输出指针变量p所在的内存地址编号 ———————————————— 版权声明:本文为CSDN博主「Sherry的成长之路」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/m0_73258399/article/details/128325295
三、动态内存分配与指向它的指针变量
1、什么是动态内存分配
动态内存分配就是使用户可以根据自己的需要,向系统申请所需大小的内存空间;由于没有声明部分来定义它们是为变量的地址还是为数组的地址,所有只能通过指针来引用它们。
2、怎样建立内存的动态分配
①使用malloc函数
malloc(int size);例如:
char *p=(char *)malloc(100)
用于分配一个大小为size的内存区域。
②使用calloc函数
calloc(unsigned n,int size);例如:
int *p=(int *)calloc(10,sizeof(int));
用于分配n个大小为size的连续内存区域,可以为一维数组开辟动态内存空间,n为数组元素个数,每个数组元素大小为size。
③使用realloc函数
realloc(void * p,unsigned int size);例如:
realloc(p,sizeof(int)*6);
用于重新分配已经通过malloc函数或calloc函数开辟的内存空间,可以改变其内存空间的大小
④使用free函数
void free(void * p);例如:
free(p);
用于释放指针变量p所指向的动态内存空间,使得这部分空间能被其他变量使用,否则这段内存空间需要等到程序结束后才会被释放。
每次使用完动态内存空间的时候需要释放内存空间。
开辟的内存空间大小size一般由sizeof(数据类型);来进行计算。
malloc和calloc函数所开辟的内存空间默认是空类型(void)的,所以需要在其之前加上一个强制类型转换。
(注意:以上函数的声明在stdlib.h头文件中,使用这些函数之前需要包含stdlib.h头文件)
四、内存四区与数据存储
1、内存四区
在系统为程序开辟内存时,将内存区域划分为4块,分别为:
栈区:存放函数的形参、局部变量等。由编译器自动分配和释放,当函数执行完毕时自动释放。
堆区:用于动态内存的申请与释放,一般由程序员手动分配和释放,若程序员不释放,则程序结束时由操作系统回收。
全局静态常量区(全局区):存放常量(一般是字符串常量和其他常量)、全局变量和静态变量,在程序结束后由操作系统释放。
代码区:存放可执行的代码,一般为CPU 执行的机器指令。
2、数据存储
计算机中的数据都是以二进制补码形式存储的,内存中数据的存储又分为两种存储方式:大端存储和小端存储。
大端存储:数据按照高位在前低位在后的方式存储。
如:1的二进制补码的大端存储为 00000001
小端存储:数据按照低位在前高位在后的方式存储。
如:1的二进制补码的小端存储为 01000000
大端存储便于人类阅读和查看数据,而小端存储便于计算机读取数据。