前言
如需理解数组指针,需要先理解[[栈和堆]]。
数组指针详解:
现定义一个变量,并为其分配内存:
char *buffer = (char *)malloc(100);
*buffer = 'A';
详解:
-
buffer
存储在栈中buffer
是一个局部变量,它是一个指针,存储在栈中。这个指针buffer
的值是malloc
函数分配内存的首地址。
-
*buffer:
*buffer
存储在堆中*buffer
是指针buffer
指向内存地址处的值。通过malloc
函数分配的 100 个字节的内存块位于堆中。可以通过*buffer
访问和修改堆中内存的值。
-
&buffer
是指针buffer
变量本身的地址&buffer
变量本身的地址在栈中,因为buffer
是一个局部变量,这个地址与堆中内存地址无关。
为了更好地理解,可以查看代码运行时的内存图:
栈 (Stack):
+-----------------+
| buffer | -> 指向堆中分配的100字节内存块的首地址
| ... |
+-----------------+
| 返回地址等其他数据 |
+-----------------+
堆 (Heap):
+-----------------+
| *buffer ('A') |
| ... (99字节) |
+-----------------+
拓展——操作堆内存中的数据:
- 代码
char *buffer = (char *)malloc(100);
*buffer = 'A';
printf("%c\n", *buffer);
- 输出
A
- 代码
char *buffer = (char *)malloc(100);
buffer = "Hello, World!";
printf("%s\n", buffer);
*buffer = 'A';
printf("%c\n", *buffer);
- 输出
Hello, World!
[1] 60387 bus error ./demo
代码之所以会报错:
此处给buffer
赋值,并非将Hello, World!
写入到malloc
分配的内存中,而是将buffer
的值改为了字面值Hello, World!
的地址。(可以理解为buffer
重新指向了一块只读内存地址,内存中的数据是Hello, World!
)
而字面值存储在只读数据段中,如果尝试用*buffer
修改,就会导致段错误(segmentation fault)。
正确做法:
#include <string.h>
strcpy(buffer, "Hello, World!");
*buffer = 'A';
- 输出
Hello, World!
Aello, World!
- 也可以通过
snprintf
函数来进行赋值
snprintf(buffer, 100, "Hello, World!");
如此一来,再通过*buffer
修改buffer
内存空间的值,就不会发生错误。
- 值得了解的是,操作
buffer
的值,还可以通过“指针算数”的方式实现:
*buffer = 'A'; // 修改第一个内存处的值
*(buffer + 1) = 'B'; // 修改第二个内存处的值
buffer[2] = 'C'; // 修改第三个内存处的值
为了防止代码阅读性变差,应防止用第二种方式来读写。
任何时候都应注意,在堆中分配的内存,一定要在用完之后即使释放,防止内存泄漏!