代码实现
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = (int *)malloc(10 * sizeof(int));
if (ptr == NULL) {
perror("malloc");
return 1;
}
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 2; j++) {
*(ptr + i * 2 + j) = i + j;
}
}
// 验证赋值结果
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 2; j++) {
printf("%d ", *(ptr + i * 2 + j));
}
printf("\n");
}
free(ptr);
return 0;
}
指针运算原理
- 在
*(ptr + i * 2 + j) = i + j;
这行代码中,ptr
是指向动态分配内存块起始地址的指针。
- 对于二维数组
a[5][2]
,在内存中是按行存储的。所以当要访问 a[i][j]
时,实际内存地址的计算需要考虑到行和列的偏移。
i * 2
表示跳过 i
行,因为每行有 2
个 int
类型元素,每个 int
类型元素占 sizeof(int)
字节。+ j
表示在当前行内偏移 j
个元素位置。
- 最终
ptr + i * 2 + j
计算出了 a[i][j]
在连续内存中的实际地址,通过 *
解引用操作符对该地址的内容进行赋值。
与传统二维数组定义方式的差异
内存管理
- 动态分配内存(使用
malloc
):
- 内存是在运行时动态分配的,通过
malloc
函数向操作系统申请一块指定大小的内存块。这使得程序在运行时可以根据实际需求灵活调整内存大小。
- 分配的内存需要手动释放,使用
free
函数。如果忘记释放,会导致内存泄漏。
- 传统二维数组定义:
- 内存是在编译时静态分配的,其大小在编译时就已经确定,并且在程序的生命周期内保持不变。
- 不需要手动释放内存,当数组所在的作用域结束时,内存会自动被系统回收。
访问机制
- 动态分配内存(使用
malloc
):
- 通过指针运算来模拟二维数组的访问,需要手动计算元素在连续内存中的偏移地址,如上述代码中的
ptr + i * 2 + j
。
- 灵活性较高,可以根据不同的需求动态调整内存布局和访问方式。
- 传统二维数组定义:
- 可以直接使用
a[i][j]
的语法进行访问,编译器会自动处理地址计算。
- 语法更直观和简洁,但内存布局相对固定,不够灵活。