1 指针的概念
简单的说,C语言的指针是一个变量,它存储另一变量的内存地址,用于直接访问和操作该内存位置的数据。
指针是 C 语言中重要的一部分,它不仅提供了数据对象的地址信息,还提供了数据对象的类型和大小信息,使得编译器能够正确地管理内存。
2. 指针数据类型
2-1 指针基础
1. **取地址运算符 `&`**:
- 是一种一元运算符,用在数据对象左边,获取对象的首地址和所需存储空间大小。
2. **声明指针变量**:
- `int n; int* pn = &n;` 表示 `pn` 保存了 `n` 的首地址和大小。
- `char c; char* pc = &c;` 表示 `pc` 保存了 `c` 的首地址和大小。
3. **各种声明方式**:
int* pn;
int *pn;
int*pn;
这三种写法都是合法的。
2-2 指针类型的功能
1. **保存首地址**:
- 指针类型的值是目标数据对象的首地址。例如,`int* pn = &n;`,这里 `pn` 保存了 `n` 的首地址。
- 打印指针类型变量例如 `printf("pn1 = %u\n", pn1);`,可以看出它们确实为数值。
2. **存储空间大小标识**:
- 指针类型不仅保存目标对象的首地址,同时标记目标对象的存储空间大小。
- 不同的指针类型标记不同的空间大小,例如 `int*` 标识 `sizeof(int)`,`char*` 标识 `sizeof(char)`。
2-3赋值与转换
1. **不同类型指针的赋值**:
- 尝试将一个类型的指针赋值给不同类型的指针(如 `int*` 赋值给 `char*`),会产生编译错误,不能自动转换。
- 原因是虽然它们都是存储地址,但类型标记不同,标记的空间大小不同。
3. 使用指针
指针存储了数据对象的首地址和大小,因此可以使用这些信息在内存中访问或修改所指向的对象。
3.1 取值运算符 `*`
- **取值运算符 `*`**:
- 这是一个一元运算符,写在指针的左边,用于访问指针所指向的数据对象。
- 示例代码:
```
int n = 123;
int* pn = &n;
printf("%u\n", pn); // 打印 n 的首地址
printf("%d\n", *pn); // 打印 pn 指向的数据对象的值
```
- **通过指针修改数据对象**:
```
int n = 0;
int* pn = &n;
char c = 0;
char* pc = &c;
*pn = 123; // 修改 n 的值
*pc = 'A'; // 修改 c 的值
printf("n = %d\n", n);
printf("c = %c\n", c);
printf("n = %d\n", *pn);
printf("c = %c\n", *pc);
```
3.2 指针类型的大小
- **指针类型的大小**:
- 无论是 `char*` 还是 `int*`,它们的大小相同,因为它们都存储数据对象的地址。
- 在32位系统中,指针占4字节;在64位系统中,指针占8字节。
- 示例代码:
```
int n = 0;
int* pn = &n;
char c = 0;
char* pc = &c;
printf("sizeof pn = %d\n", (int)sizeof(pn));
printf("sizeof pc = %d\n", (int)sizeof(pc));
```
- **打印指针地址**:
- `%p` 是指针类型专用的占位符(常为十六进制显示),适用于32位和64位程序。
- 示例代码:
```
int n = 0;
int* pn = &n;
char c = 0;
char* pc = &c;
printf("pn = %u\n", (unsigned int)pn);
printf("pc = %u\n", (unsigned int)pc);
printf("pn = %p\n", pn);
printf("pc = %p\n", pc);
```
3.3 强制转换指针类型
- **强制转换指针类型**:
- 虽然 `int*` 和 `char*` 不能直接赋值转换,但可以使用强制转换。
- 针对同一首地址,`int*` 表达式会取 `sizeof(int)` 字节,`char*` 表达式会取 `sizeof(char)` 字节。
- 示例代码:
```
int n = 1431655765; // 85 in one byte of this 4-byte integer
int* pn = &n;
char* pc = (char *)pn; // 强制转换 int* 到 char*
printf("pn = %u\n", (unsigned int)pn);
printf("pc = %u\n", (unsigned int)pc);
printf("n = %d\n", n);
printf("*pn = %d\n", *pn);
printf("*pc = %d\n", *pc);
```
3.4 小结:
- **取值运算符 `*`**:
- 用于访问或修改指针所指向的数据对象。
- **指针类型大小**:
- 是固定的,与数据对象类型无关,通常为4字节(32位)或8字节(64位)。
- **强制转换指针类型**:
- 通过强制类型转换可以实现不同类型指针的赋值,但操作时会影响数据的视图,需要注意数据类型和大小。