C语言基础之指针(一)

2023-03-28  本文已影响0人  Eugene_iOS

C语言基础之指针(一)
C语言基础之指针(二)

1、内存那些事儿

物理内存:计算机设备中的存储固件

虚拟内存:操作系统虚拟出来的内存,当一个进程被创建或者程序运行的时候都会分配虚拟内存;由操作系统实现物理内存虚拟内存之间的映射。

虚拟内分配机制:内存(线性空间),以字节为单位,每字节都会有独一无二的地址,地址呈线性增长。数据在内存中是以大、小端字节序的方式存储。

  • 基本数据类型(int、short):以小端或大断方式存储。
  • 数组类型:在内存中会为数组分配一块连续的内存空间,按顺序存储。(数组中的基本数据类型,根据小端或大端存储,而数组元素按顺序存储)

注意:在32位系统下,每个进程的寻址范围是4G,0x00 00 00 00 ~ 0xff ff ff ff。
了解更多动态内存DRAM和静态内存SRAM

2、指针

指针就是地址(虚拟内存中的地址)。

3、指针变量

是个变量,用来存放一个地址编号,该地址编号是其它数据单元(变量/数组/结构体/函数等)的首地址。若指针存放了某个数据单元的首地址,则这个指针指向了这个数据单元,若指针存放的值是0,则这个指针为空指针。

4、指针大小

在32位系统下,所有类型的指针都是4个字节

5、指针和变量的关系

在程序中,引用变量的方法

  1. 直接通过变量的名称
    int a;
    a = 100;
  2. 也可以通过指针变量
    int *p; // 定义一个指针变量,*修饰p是个指针变量
    p = &a; // 取的地址给 p赋值,p保存了a的地址,也可说p指向了a
    *p = 100;// 在调用的时候*是取值的意思,*指针变量 等价于 指针指向的变量


6、指针的运算

6.1、指针可以加一个整数,往上指几个它指向的变量,结果还是个地址

int array[] = "hello";
int *point = array;// c语言规定:数组名数组的首地址,此时point指向数组的首地址,也是第 0 个元素的地址
point += 1;// 移动指针地址(最终移动的字节数和指针变量的类型有关)
printf("point = %p\n",point);// 输出结果为数组元素‘e’的地址(和大小端有关也存在一定关系)

6.2、两个相同类型指针可以比较大小

前提:只有两个相同类型的指针指向同一个数组元素的时候,比较大小才有意义;指向前面元素的指针小于指向后面元素的指针;

6.3、两个相同类型的指针可以做减法

前提:必须是两个相同类型的指针指向同一个数组的元素的时候,做减法才有意义;做减法的结果是,两个指针指向的中间有多少个元素。

6.4、两个相同类型的指针可以相互赋值

注意:
1、只有相同类型的指针才可以相互赋值(void *类型的除外)。
2、如果类型不同的指针想要互相赋值,必须进行强制类型转换。

6.5、指针操作方式总结

指针操作方式:取地址取内容等。

7、指针 和 数组的关系

1、指针可以保存数组元素的地址
2、可以定义一个数组,数组中有若干个相同类型的指针变量,这个数组被称为指针数组

8、指针数组

指针数组:本身是个数组,是指针数组,是若干个相同类型的指针变量构成的集合。其数组名即为指向该数据类型的指针,数组的定义等效于申请内存、定义指针和初始化。
例1:(申请内存、定义指针和初始化)
char a[ ] = {0x33, 0x34, 0x35};
等效于:

  • 申请内存;
  • 定义 char *a = 0x4000;
  • 初始化数组;

例2:(利用下标引用数组数据也等效于指针取内容.)

  • a[0]; 等效于 *a;
  • a[1]; 等效于 *(a+1);
  • a[2]; 等效于 *(a+2);


9、指针的指针:即指针的地址

int a; // 定义一个变量a
int *p;// 定义一个指针变量p,即一级指针,保存普通变量的地址(指针变量本身占4个字节)
p = &a;// 将 普通变量a的地址 赋值给 指针变量p
此时:*p == a


int **pp;// 定义一个指针的指针变量pp (二级指针:保存一级指针的地址)
pp = &p;// 将 指针变量p 赋值给 指针的指针变量pp
此时:
*pp == p
*(*pp) == *p == a


int ***ppp;// 定义一个三级指针(三级指针:保存二级指针)
ppp = &pp;
此时:*(*(*ppp)) == a
⚠️注意:p、pp、ppp都是指针变量,都占4个字节,都存放地址编号,只是类型不同

10、指针和字符串

字符串:以\0结尾的若干字符的集合。
字符串的存储形式数组字符串指针

  1. char string[100] = "Hello world!";
    定义并初始化字符数组string,来存储"Hello world!"字符集合,该字符集合是存储在string这个变量中的。可动态修改字符串内容。

  2. char *string = "Hello world!";
    定义并初始化一个指针变量string,因为char只占一个字节,只能存放字符地址编号,所以"Hello world!"字符集合不能存放在string指针变量中。此时这里string指针变量只是存放了字符‘H’的地址编号,"Hello world!"字符集合存放在内存的文字常量区。不可动态修改字符串内容。

  3. char *string = (char *)malloc(13 * sizeof(char));
    strcpy(string, "Hello world!")
    动态申请 13(12个字符 + 1个\0结尾字符) 个字节的存储空间,将首地址赋值给指针变量string。最后将字符串"Hello world!"拷贝到string指向的内存空间。可动态修改字符串内容。

拓展
char *string = "Hello world!";
字符数组:在内存(栈、静态全局区)中开辟了一段空间存放字符串。
字符串指针:在文字常量区开辟了一段空间存放字符串,将字符串的首地址赋值给字符指针。
:使用malloc函数在堆区申请空间,将字符串拷贝到堆区
创建操作局部变量时,可使用字符数组;创建使用全局变量时,可在堆区申请内存使用,堆区内存要手动申请、手动释放;

⚠️ 注意:字符串的可修改性
1、栈和全局区中的内存是可以修改的。
2、文字常量区的内存是不可修改的。
3、堆区的内容是可以修改的

上一篇下一篇

猜你喜欢

热点阅读