指针的本质:指针是一个变量,存储的是另一个变量的内存地址。
解引用:通过指针访问其指向的内存地址中的数据。
步长:当指针进行算术运算(如 p++
或 p + 1
)时,指针移动的字节数。
指针的步长由以下两个因素决定:
在 C 语言中,每个变量都有一个存储位置,也就是它在内存中的地址。比如你定义一个变量 int a = 5;,它就占据了内存中的某个位置,这个位置有一个唯一的地址。指针就是用来存储这个地址的。指针是一个变量,它保存的是另一个变量的内存地址。定义指针时,需要指定它指向的变量类型。例如,int *p; 这表示 p 是一个指向 int 类型变量的指针。(也可以抽象成一根针指向a所占据的地址)
可以理解为以下两种方式:
创建一个int*pc=&a;
为什么a前面会出现一个&符号?又是什么?——&是取地址符,&a也就是把a的地址取出来赋值给pc,*说明pc是一个指针,int说明pc这根针指向的地址内部存储的是int型;
a是一个整型变量,整型变量占用4个字节,每个字节都有地址,那&a取出来的是哪一个地址呢?——取出的是第一个字节的地 (较小的地址);
*pc可以找到a,也就是*pc=a, 如果要将a的值修改那可以直接*pc=修改值
1.在栈区随机分配一个地址存放变量a;假设为ox0012ff43,第一种方法理解为随机分配个地址给pc用来存放a的地址,注意pc也会分配一个地址;
2.把pc抽象为一根针,指着a的上层,也就是指向a的地址ox0012ff43,pc也会分配一个地址,同上;
注意:二者等价
以下是常见数据类型的指针步长示例(假设在32位或64位系统中,int
占4字节,char
占1字节,double
占8字节):
char*
指针类型大小:char
占1字节。
步长:每次 p++
或 p + 1
,指针移动1字节。
示例:
c
char arr[] = {'a', 'b', 'c'};
char *p = arr; // p指向arr[0]
p++; // p现在指向arr[1],移动1字节
int*
指针类型大小:int
占4字节。
步长:每次 p++
或 p + 1
,指针移动4字节。
示例:
int arr[] = {10, 20, 30};
int *p = arr; // p指向arr[0]
p++; // p现在指向arr[1],移动4字节
double*
指针类型大小:double
占8字节。
步长:每次 p++
或 p + 1
,指针移动8字节。
示例:
double arr[] = {1.1, 2.2, 3.3};
double *p = arr; // p指向arr[0]
p++; // p现在指向arr[1],移动8字节
用法:定义一个int a = 0x11223344 ;
变量存储在内存单元如图:
这里相信大家有疑问,为什么不是11223344呢,是因为变量存储在内存单元中存在大小端问题,可参考——大小端
如果我们只是想改变其中一个字节的数据那我们就可以将变量a强制转换为char*类型
#include
int main() {
int a = 0x11223344;
char *p = (char *)&a; // 将int指针强制转换为char指针
printf("Before: a = 0x%x\n", a);
p[1] = 0xAA; // 修改第1字节为0xAA
printf("After: a = 0x%x\n", a);
return 0;
}
输出:
Before: a = 0x11223344
After: a = 0x1122aa44
想修改几个字节就强制转换为所对应步长的类型;
以上述说的都是一级指针,只有一颗*
就不再赘述;
顾名思义就有2颗*
二级指针是指 指向指针的指针。在C语言中,指针是一个变量,存储的是另一个变量的地址;而二级指针存储的是一个指针变量的地址。
一级指针:指向普通变量(如 int*
指向 int
)。
int **pc; // pc 是一个二级指针,指向一个 int* 类型的指针
类型 **指针变量名;
int *p =& a ; int **pc= & pc ;
修改指针变量的值
通过二级指针,可以在函数中修改指针变量的值。
#include
#include
void allocateMemory(int **ptr) {
*ptr = (int *)malloc(sizeof(int)); // 分配内存
**ptr = 100; // 修改指针指向的值
}
int main() {
int *p = NULL;
allocateMemory(&p); // 传递指针的地址
printf("Value: %d\n", *p); // 输出 100
free(p); // 释放内存
return 0;
}
allocateMemory
函数接收一个二级指针 int **ptr
。
*ptr
解引用后得到一级指针 int*
,可以修改它的值。
**ptr
解引用后得到 int
类型的值。
使用二级指针动态分配二维数组。
#include
#include
int main() {
int rows = 3, cols = 4;
int **arr;
// 分配行指针
arr = (int **)malloc(rows * sizeof(int *));
// 为每一行分配列
for (int i = 0; i < rows; i++) {
arr[i] = (int *)malloc(cols * sizeof(int));
}
// 赋值
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
arr[i][j] = i * cols + j;
}
}
// 打印
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
// 释放内存
for (int i = 0; i < rows; i++) {
free(arr[i]);
}
free(arr);
return 0;
}
arr
是一个二级指针,指向一个指针数组。
首先为行分配内存,然后为每一行分配列。
通过 arr[i][j]
访问二维数组元素。
最后逐行释放内存。
**通过二级指针返回动态分配的指针。
#include
#include
void createArray(int **arr, int size) {
*arr = (int *)malloc(size * sizeof(int)); // 分配内存
for (int i = 0; i < size; i++) {
(*arr)[i] = i * 2; // 初始化数组
}
}
int main() {
int *arr = NULL;
int size = 5;
createArray(&arr, size); // 传递指针的地址
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]); // 输出 0 2 4 6 8
}
free(arr); // 释放内存
return 0;
}
createArray
函数通过二级指针 int **arr
返回动态分配的数组。
*arr
解引用后得到一级指针 int*
,可以操作动态数组。
由于c语言并不要求我们学习多级指针,且多级指针复杂难懂,这里就不再赘述,感兴趣的佬可参考 多级指针解析
要求我们学习多级指针,且多级指针复杂难懂,这里就不再赘述,感兴趣的佬可参考 多级指针解析**
int*
char*
double*
float*
以上类型开头讲述过,还有void*等特殊指针也不再赘述
点赞关注不迷路哦 !!!