29、指针进阶1:深入理解指针
指针是C语言中的核心概念,它提供了对内存的直接访问和控制能力。通过深入理解指针,我们肯定可以编写更高效、更灵活的程序,然后少踩坑。
指针与内存模型
指针与地址的概念
在C语言中,指针是一个变量,其存储的是另一个变量的内存地址。通过指针,我们可以直接访问和操作内存中的数据。指针变量的类型决定了它所指向的数据的类型和大小。
内存****布局与地址空间
C语言程序的内存布局通常包括代码段、数据段、堆和栈几部分。
- 代码段存储程序的机器指令,也就是咱写的那些代码
- 数据段存储全局变量和静态变量
- 堆用于动态内存分配,对应
malloc
和free
的函数调用 - 栈则用于存储局部变量和函数调用信息。
地址空间是指程序可以访问的内存地址范围。
- 在32位系统上,地址空间通常是4GB(或更小,取决于操作系统和硬件)。
- 在64位系统上,地址空间要大得多。
推荐阅读:指针介绍
指针运算的深入
算术运算与指针偏移
指针可以进行算术运算,如加法、减法和自增/自减。这些运算实际上是对指针所指向的内存地址进行偏移。例如,如果**ptr
是一个指向int
类型的指针,那么ptr+1
将指向下一个int
**类型的数据,而不是简单地将地址加1。
指针的算术运算考虑了所指向数据类型的大小。
示例代码
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr; // 指向数组的第一个元素
// 指针算术运算
printf("arr[0]: %d, *(ptr): %d\n", arr[0], *(ptr)); // 输出1
printf("arr[1]: %d, *(ptr+1): %d\n", arr[1], *(ptr+1)); // 输出2
return 0;
}
指针与数组的高级应用
动态数组的实现
动态数组是使用指针和动态内存分配(如malloc
和free
函数)来实现的(内存管理)。与静态数组相比,动态数组的大小可以在运行时确定,并且可以根据需要动态调整。
多维数组与指针
多维数组在内存中实际上是连续存储的,但可以通过指针和索引来访问,只不过是我们从逻辑层把它理解为了多维数组。
**示例代码(**https://godbolt.org/z/zx771M7M4****)
#include <stdio.h>
#include <stdlib.h>
int main() {
// 动态数组
int n = 10;
int *dynamicArr = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
dynamicArr[i] = i + 1;
}
for (int i = 0; i < n; i++) {
printf("%d ", dynamicArr[i]);
}
printf("\n");
free(dynamicArr); // 释放动态分配的内存
// 多维数组与指针
int rows = 3;
const int cols = 4;
int (*multiDimArr)[cols] = (int (*)[cols])malloc(rows * cols * sizeof(int));
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
multiDimArr[i][j] = i * cols + j + 1;
}
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", multiDimArr[i][j]);
}
printf("\n");
}
free(multiDimArr); // 释放动态分配的内存
return 0;
}
输出:
1 2 3 4 5 6 7 8 9 10
1 2 3 4
5 6 7 8
9 10 11 12
指针与字符串的深入
字符串的底层表示
在C语言中,字符串实际上是一个以空字符(\0
)结尾的字符数组。字符串的底层操作实际上是对字符数组的操作,而指针访问这些字符数组则很方便。
字符串处理函数与指针
C标准库提供了一系列字符串处理函数,如strlen
、strcpy
、strcat
等。这些函数通常接受指向字符串的指针作为参数,并返回指向结果字符串的指针或整数值(如字符串的长度)。
**示例代码(**https://godbolt.org/z/d37norMoo****)
#include <stdio.h>
#include <string.h>
int main() {
char str1[50] = "Hello, World!";
char str2[50];
// 使用字符串处理函数
printf("Length of str1: %lu\n", strlen(str1)); // 输出字符串的长度
strcpy(str2, str1); // 复制字符串
printf("Copied string: %s\n", str2);
strcat(str2, " - Welcome!"); // 连接字符串
printf("Concatenated string: %s\n", str2);
return 0;
}
通过深入理解指针,你应该可以写出更灵活健壮的程序吧。
