【C语言】(8)—指针2
文章目录
- 一、指针基础回顾
- 1.1 指针声明与初始化
- 1.2 指针的解引用
- 二、数组名的本质
- 2.1 数组名即首元素地址
- 2.2 两个例外情况
- 三、使用指针访问数组
- 3.1 指针算术运算访问数组
- 3.2 数组下标与指针的等价性
- 四、一维数组传参的本质
- 五、冒泡排序算法实现
- 六、二级指针
- 七、指针数组
一、指针基础回顾
指针本质上是一个变量,其存储的是内存地址。通过指针,我们可以直接访问和操作内存中的数据,这赋予了C语言极高的灵活性和效率。
1.1 指针声明与初始化
int a = 10; // 定义一个整型变量
int *p = &a; // 定义一个指向整型的指针,并初始化为a的地址
这里p是一个指针变量,它存储的是变量a的内存地址。&是取地址运算符,用于获取变量的内存地址。
1.2 指针的解引用
printf("%d\n", *p); // 输出10,*p表示访问p指向的值
*p = 20; // 通过指针修改a的值
printf("%d\n", a); // 输出20
二、数组名的本质
数组名在大多数情况下代表数组首元素的地址,但有两个重要的例外情况。
2.1 数组名即首元素地址
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
printf("&arr[0] = %p\n", &arr[0]);
printf("arr = %p\n", arr);
输出结果将显示&arr[0]和arr的值相同,证明数组名确实是首元素地址。
2.2 两个例外情况
sizeof(数组名):此时数组名表示整个数组,计算的是整个数组的大小
printf("%d\n", sizeof(arr)); // 输出40(假设int为4字节,10个元素)
&数组名:此时取到的是整个数组的地址
printf("&arr = %p\n", &arr);
printf("&arr+1 = %p\n", &arr+1); // 会跳过整个数组(40字节)
三、使用指针访问数组
3.1 指针算术运算访问数组
int arr[10] = {0};
int *p = arr;
for(int i=0; i<10; i++) {scanf("%d", p+i); // 等价于&arr[i]
}
for(int i=0; i<10; i++) {printf("%d ", *(p+i)); // 等价于arr[i]
}
3.2 数组下标与指针的等价性
arr[i]和*(arr+i)是完全等价的,编译器会将前者转换为后者:
arr[3] = 10; // 等价于
*(arr+3) = 10; // 同样效果
四、一维数组传参的本质
数组作为函数参数传递时,实际上传递的是数组首元素的地址,而非整个数组。
void test(int arr[]) {printf("%d\n", sizeof(arr)); // 输出指针大小(4或8字节)
}int main() {int arr[10] = {0};printf("%d\n", sizeof(arr)); // 输出40(整个数组大小)test(arr);return 0;
}
五、冒泡排序算法实现
void bubble_sort(int arr[], int sz) {for(int i=0; i<sz-1; i++) {for(int j=0; j<sz-i-1; j++) {if(arr[j] > arr[j+1]) {int tmp = arr[j];arr[j] = arr[j+1];arr[j+1] = tmp;}}}
}
六、二级指针
int a = 10;
int *pa = &a; // 一级指针
int **ppa = &pa; // 二级指针
七、指针数组
int arr1[] = {1,2,3,4,5};
int arr2[] = {2,3,4,5,6};
int arr3[] = {3,4,5,6,7};
int *parr[3] = {arr1, arr2, arr3};for(int i=0; i<3; i++) {for(int j=0; j<5; j++) {printf("%d ", parr[i][j]); // 模拟二维数组访问}printf("\n");
}