第七章 指针
第一节 指针基础与使用详解
概述
指针是C语言中最具特色和威力的一个概念。掌握指针的基本用法,是理解C语言深层次机制和高效编程的关键。本节内容将系统讲解指针的定义、声明、使用、指针与变量的关系以及常见操作。通过本节学习,考生能够理解指针的本质,掌握指针变量的声明和赋值,能够编写使用指针的程序,并避免常见错误。
核心概念
- 指针(Pointer):指针是存储变量地址的变量,即指向某一内存单元的变量。
- 指针变量:专门存储地址的变量,其类型决定了指针指向的数据类型。
- 地址运算符(&):用于获取变量的地址。
- 间接访问运算符(*):通过指针访问或修改指针所指向的变量。
- 空指针(NULL):不指向任何有效地址的指针。
原理分析
指针的核心在于变量在内存中的地址。每个变量在计算机内存中都有唯一的地址,指针变量存储该地址,从而可以通过指针间接访问变量。指针类型与数据类型相对应,指针运算遵循数据类型大小(如int指针向后移动一单位是4字节)。
指针变量本身也占内存空间,通常为4或8字节(取决于系统架构)。使用指针可以实现动态内存管理、数组操作、函数传参(尤其是传递大型结构体或实现函数返回多个值)等。
详细内容
1. 指针的定义和声明
定义指针变量的一般格式为:
数据类型 *指针变量名;例如:
int *p; // p是一个指向int类型的指针变量 char *ch; // ch是一个指向char类型的指针变量注意:
*号与变量名之间可以有空格,不影响含义。- 指针类型必须与它指向的数据类型匹配。
2. 指针的初始化与赋值
- 指针变量必须初始化为有效地址或NULL,否则指针成为“悬空指针”,可能导致程序崩溃。
- 获取变量地址:
int a = 10; int *p = &a; // p存储变量a的地址 - 赋值给指针:
int *p; p = &a;
3. 通过指针访问变量
- 使用间接访问运算符
*访问指针指向的变量:int a = 10; int *p = &a; printf("%d", *p); // 输出10 *p = 20; // 修改a的值为20 - 修改指针指向变量的值,实际是修改变量本身。
4. 指针类型与指针运算
指针类型决定了指针运算时的步长。例如:
int *p,p+1表示向后移动一个int大小(通常4字节)。char *p,p+1表示向后移动一个字节。
指针加减操作:
p++:指针指向下一个元素地址。p--:指针指向上一个元素地址。
指针比较:
- 指针可以比较大小,但只能在同一数组或内存块范围内有效。
5. 空指针和野指针
空指针用
NULL表示,不指向任何合法地址。野指针是未初始化或指向已释放内存的指针,使用野指针会引发严重错误。
int *p = NULL; // 安全的空指针
6. 指针与数组的关系
数组名本质是指向数组第一个元素的指针。
可以用指针遍历数组元素。
int arr[3] = {1,2,3}; int *p = arr; // 等价于 int *p = &arr[0]; printf("%d", *(p+1)); // 输出2
7. 指针的输入输出
- 指针变量本身存储地址,通常用%p格式输出。
- 通过间接访问运算符访问指向变量的值。
实例分析
实例1:指针访问变量及修改
#include <stdio.h>
int main() {
int a = 5;
int *p = &a;
printf("a的值: %d\n", a); // 5
printf("通过指针访问a的值: %d\n", *p); // 5
*p = 10; // 修改a的值
printf("修改后a的值: %d\n", a); // 10
return 0;
}
分析:
- 指针p存储变量a的地址。
- 通过
*p可以访问和修改a。 - 说明指针是变量访问和操作的间接工具。
实例2:指针遍历数组
#include <stdio.h>
int main() {
int arr[5] = {10, 20, 30, 40, 50};
int *p = arr; // 指向数组首元素
for(int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, *(p + i));
}
return 0;
}
分析:
- 指针p指向数组首元素。
- 通过指针偏移遍历数组元素。
- 体现指针与数组的紧密联系。
实例3:指针与函数参数传递
#include <stdio.h>
void swap(int *x, int *y) {
int temp = *x;
*x = *y;
*y = temp;
}
int main() {
int a = 3, b = 4;
printf("交换前: a = %d, b = %d\n", a, b);
swap(&a, &b);
printf("交换后: a = %d, b = %d\n", a, b);
return 0;
}
分析:
- 通过传递变量地址,实现函数内部修改外部变量。
- 指针是实现函数参数“传址”的关键。
常见误区
- 指针未初始化直接使用
- 错误:
int *p; *p = 10; // 未初始化,可能指向任意地址 - 正确:初始化指针,确保指向合法地址。
- 错误:
- 错误理解指针类型
- 指针类型必须与指向数据类型匹配,否则访问时会出现错误。
- 错误使用间接访问运算符
- 对非指针变量使用
*,编译错误。
- 对非指针变量使用
- 野指针使用
- 指向已释放内存或未分配内存。
- 指针运算越界
- 指针加减超出合法数组范围,导致未定义行为。
应用场景
- 动态内存分配:通过指针管理堆内存,实现灵活数据结构。
- 函数参数传递:实现传址传递,修改函数外变量。
- 数组和字符串操作:使用指针遍历、修改数组和字符串。
- 数据结构实现:链表、树等结构需要大量指针操作。
- 系统底层编程:操作硬件寄存器、内存地址。
知识拓展
- 指针与多级指针(指向指针的指针)
- 指针与结构体
- 函数指针及其应用
- 指针与动态内存管理(malloc、free)
- 指针与数组、字符串的高级用法
总结回顾
本节重点围绕指针的基本概念和用法展开,深入讲解了指针的定义、声明、赋值、访问和指针与数组的联系。通过典型实例展示了指针的实际应用。特别强调了指针使用中的安全问题,如初始化和避免野指针。掌握本节内容,能够为后续学习指针的高级用法,比如多级指针、函数指针、动态内存管理打下坚实基础。
通过本节内容的学习,考生应能够做到:
- 理解指针的本质和意义
- 正确声明和使用指针变量
- 通过指针访问和修改变量
- 利用指针遍历数组
- 避免指针使用中的常见错误
掌握这些内容是通过全国计算机等级考试二级C语言程序设计考试的重要保障。祝学习顺利!