前言
一、指针基本概念介绍
在 C 语言中,指针是一种用于存储内存地址的数据类型。指针可以存储任何数据类型的内存地址,包括基本数据类型、数组、结构体、函数等。通过指针,可以实现对内存中某个位置的直接访问和修改,这是 C 语言中很多高级特性的实现基础。
在定义指针变量时,需要指定指针变量所指向的数据类型。语法格式如下:
type *ptr;
其中 type 是指针变量所指向的数据类型,* 表示这是一个指针类型的变量,ptr 是指针变量的名称。例如,以下代码定义了一个指向整型数据的指针变量:
int *p;
指针变量在初始化之前,通常会被赋予 NULL 或者 0 这样的无效地址。指针变量可以通过取地址符 & 来获取某个变量的内存地址。例如,以下代码获取了整型变量 num 的内存地址,并将其赋给指针变量 p:
int num = 10; int *p = # // p 中保存 num 的内存地址
二、指针的大小
在C语言中,指针的大小与它所指向的数据类型有关。由于不同类型所占据的空间大小是不同的,指向不同类型的指针也会有不同的大小。
在32位的系统中,指针的大小通常是4个字节,即32位;在64位的系统中,指针的大小通常是8个字节,即64位。但是,这仅仅是指针变量本身所占据的空间大小,指针所指向的实际数据类型的大小并不一定相同。
例如,以下代码分别定义了指向不同类型数据的指针:
int *p_int; char *p_char; float *p_float;
在大多数编译器实现中,这些指针变量都占据 4 个字节(32位系统)或 8 个字节(64位系统)的空间。但是,这些指针所指向的实际数据类型占据的空间是不同的。int 类型通常占据 4 个字节,char 类型通常占据 1 个字节,float 类型通常占据 4 个字节。因此,在通过这些指针来访问内存中的数据时,每种类型需要根据它所占据的空间数来确定访问的字节数。
另外,需要注意的是函数指针的大小,函数指针与普通指针的大小并不相同。函数指针(指向函数的指针)的大小取决于系统的架构和指针实现的细节。
总的来说,指针的大小取决于系统的位数和指针所指向的数据类型。对于特定的系统和编译器,可以使用 sizeof 运算符来计算指针的大小。
在x86中指针大小运算结果:
在x64中指针大小运算结果:
三、使用指针访问变量和变量地址
在 C 语言中,使用指针可以访问变量的值和内存地址。
访问变量的值可以通过指针运算符 * 来实现。例如,以下代码定义了一个整型变量 num 和一个指向 num 的指针变量 p,并使用指针变量 p 访问 num 的值:
int num = 10; int *p = # // p 中保存 num 的内存地址 int value = *p; // value 等于 num 的值,也就是 10
在这个例子中,使用取地址符 & 来获取 num 变量的内存地址,并将其赋给指针变量 p。然后,使用指针运算符 * 访问 p 指向的内存地址中存储的值,即 num 变量的值。
访问变量的内存地址可以直接使用取地址符 &。例如,以下代码访问 num 变量的内存地址,并将其打印出来:
int num = 10; int *p = # // p 中保存 num 的内存地址 printf("%p", &num); // 打印 num 的内存地址
在这个例子中,printf 函数使用 %p 格式化字符串打印 num 变量的内存地址,使用取地址符 & 获取了 num 变量的内存地址。
四、使用指针遍历数组
指针可以用来遍历数组,可以直接通过指针来访问数组元素的值。
以下是一个使用指针遍历数组的示例代码:
int arr[5] = {1, 2, 3, 4, 5}; int *p = arr; // p 指向数组的第一个元素 for (int i = 0; i < 5; i++) { printf("%d ", *(p + i)); }
在这个示例中,数组 arr 包含了5个整型元素,定义了一个指针变量 p 指向数组的第一个元素。使用 for 循环遍历了数组中的所有元素,在每一次循环中,通过指针 p 加上偏移量 i 来访问数组的每一个元素的值,即 *(p + i)。
需要注意的是,在使用指针遍历数组时,指针的类型必须匹配数组元素的类型,否则会导致访问内存时出现错误。另外,指针变量 p 中并不存储数组的长度信息,因此在进行指针遍历时需要保证不越界。
也可以使用指针或者下标来访问数组元素的值。介绍一下使用 p[i] 的方式来遍历数组。
p[i] 和 *(p + i) 是等价的方式,都是通过指针偏移量来访问数组元素的值。例如,以下代码使用 p[i] 的方式遍历数组:
int arr[5] = {1, 2, 3, 4, 5}; int *p = arr; // p 指向数组的第一个元素 for (int i = 0; i < 5; i++) { printf("%d ", p[i]); // 使用 p[i] 的方式访问数组元素的值 }
在这个示例中,与使用指针和偏移量计算元素地址访问数组元素的方式不同,使用 p[i] 的方式直接使用下标 i 来访问数组中的元素。p[i] 实际上等价于 *(p + i)。
需要注意的是,在使用 p[i] 的方式遍历数组时,指针变量 p 必须指向数组的第一个元素。在函数参数中传递数组时,数组会退化为指向第一个元素的指针,因此也可以使用 p[i] 的方式来访问数组中的元素。
总结
本篇文章我们只是简单的了解了指针的基本概念和基本用法,后续我们还会讲解指针的高级用法,大家可以多多关注我将持续更新文章。