C 指针
C - 指针
Section titled “C - 指针”指针是 C 语言最强大和最独特的特性之一。它们允许直接操作内存、高效处理数据(例如将大型结构体传递给函数)、进行动态内存分配,并且对于构建复杂数据结构至关重要。
从核心上讲,一个 指针 是一个存储另一个变量的 内存地址 的变量。
您声明的每个变量都驻留在计算机内存中的特定位置。这个位置有一个唯一的地址。您可以使用地址运算符(&)获取变量的地址。
为了可移植地打印内存地址,请使用 printf 的 %p 格式说明符,并将地址转换为 (void *)。
#include <stdio.h>
int main(void) { int count = 10; double price = 99.99; char grade = 'A';
// Get and print the memory address of each variable // 获取并打印每个变量的内存地址 printf("Address of count: %p\n", (void *)&count); printf("Address of price: %p\n", (void *)&price); printf("Address of grade: %p\n", (void *)&grade);
return 0;}编译并运行此代码时,您将看到表示内存位置的十六进制数字(具体数值在每次运行和不同系统上都会变化):
Address of count: 0x7ffc1a4b9c8cAddress of price: 0x7ffc1a4b9c90Address of grade: 0x7ffc1a4b9c8b什么是指针?
Section titled “什么是指针?”指针变量被声明用于 存储 这样的地址。声明指定了指针将指向的数据类型。这一点至关重要,因为它告诉编译器在对指针进行解引用时需要读取/写入多少字节,以及如何执行指针算术。
指针声明语法:
type *pointer_variable_name;这里,type 是指针将指向的变量的数据类型(例如,int、double、char、struct Point)。星号(*)表示 pointer_variable_name 是一个指针。
指针声明示例:
int *p_int; // Pointer to an integer// 指向整数的指针double *p_double; // Pointer to a double// 指向双精度浮点数的指针char *p_char; // Pointer to a character// 指向字符的指针struct Point *p_pt; // Pointer to a struct Point variable// 指向结构体 Point 变量的指针注意:任何指针变量中实际存储的 值(无论它指向什么类型)都是一个内存地址(通常表示为一个大的无符号整数)。type 部分对于编译器在使用指针时的解释至关重要。
如何使用指针?
Section titled “如何使用指针?”涉及指针的基本操作包括:
- 声明: 声明一个适当类型的指针变量。
- 赋值: 将变量的地址(使用
&获取)赋给指针。 - 解引用: 使用解引用(或间接寻址)运算符(
*)访问存储在指针中的 地址处 的值。
示例:
#include <stdio.h>
int main(void) { int score = 95; int *p_score; // 1. Declare a pointer to an integer // 1. 声明一个指向整数的指针
p_score = &score; // 2. Assign the address of 'score' to 'p_score' // 2. 将 'score' 的地址赋给 'p_score'
printf("Address of score variable : %p\n", (void *)&score); printf("Address stored in p_score : %p\n", (void *)p_score); printf("Value of score variable : %d\n", score);
// 3. Dereference p_score to get the value stored at that address // 3. 解引用 p_score,获取该地址处存储的值 printf("Value via p_score (*p_score): %d\n", *p_score);
// Modifying the value *through* the pointer // 通过指针修改值 *p_score = 100; // Change the value at the address p_score holds // 改变 p_score 所持有的地址处的值 printf("New value of score : %d\n", score); // Original 'score' is changed! // 原始变量 'score' 的值改变了!
return 0;}输出(地址会变化):
Address of score variable : 0x7ffd6e0f8a5cAddress stored in p_score : 0x7ffd6e0f8a5cValue of score variable : 95Value via p_score (*p_score): 95New value of score : 100NULL 指针
Section titled “NULL 指针”在使用指针之前对其进行初始化至关重要。如果您没有一个有效的地址可以立即赋值,请将指针初始化为 NULL。NULL 是一个特殊的宏(在 <stddef.h>、<stdio.h> 等头文件中定义),表示一个空指针常量(通常是 (void *)0)。
一个 NULL 指针表示该指针有意不指向任何有效的内存位置。
#include <stdio.h>#include <stddef.h> // For NULL definition // 用于 NULL 定义
int main(void) { int *p_data = NULL; // Initialize pointer to NULL // 将指针初始化为 NULL
printf("Value of p_data: %p\n", (void *)p_data);
// --- Attempting to dereference a NULL pointer causes Undefined Behavior (often a crash!) --- // --- 尝试解引用 NULL 指针会导致未定义行为(通常是程序崩溃!) --- // *p_data = 10; // DANGER! DO NOT DO THIS! // 危险!不要这样做!
// Always check if a pointer is NULL before dereferencing // 在解引用之前,务必检查指针是否为 NULL if (p_data != NULL) { printf("Value pointed to: %d\n", *p_data); } else { printf("p_data is a NULL pointer.\n"); }
// Alternative check // 另一种检查方式 if (!p_data) { // Evaluates to true if p_data is NULL // 如果 p_data 为 NULL,则此条件为真 printf("p_data is NULL (checked using !p_data).\n"); }
return 0;}输出:
Value of p_data: (nil) // Or 0x0, depending on system printf// 或 0x0,取决于系统的 printf 实现p_data is a NULL pointer.p_data is NULL (checked using !p_data).解引用 NULL 指针是一个常见的编程错误,通常会导致程序崩溃(段错误 Segmentation Fault)。在使用指针之前,尤其是从 malloc 等函数返回或在数据结构中使用的指针,务必进行检查。
C 指针概念
Section titled “C 指针概念”指针实现了许多基本的 C 编程技巧:
| Concept | Description |
|---|---|
| 概念 | 描述 |
| 指针算术 | 对指针执行算术运算(+、-、++、--)。递增一个指针会使其向前移动 sizeof(pointed-to-type) 字节。对于数组遍历至关重要。 |
| 指针与数组 | 在表达式中,数组名通常会“衰退”为一个指向其第一个元素的指针。指针常用于高效地遍历数组。 |
| 指针数组 | 创建每个元素都是指针的数组(例如,字符串数组,其中每个元素指向字符串的第一个字符)。 |
| 指向指针的指针(二级指针) | 一个存储另一个指针地址的指针(例如,int **p)。用于修改传递给函数的指针或用于指针数组。 |
| 指针与函数 | 将指针作为参数传递给函数,允许函数修改原始数据(模拟传引用)。函数也可以返回指针(例如 malloc)。 |
| 动态内存分配 | 使用 malloc、calloc、realloc(来自 <stdlib.h>)等函数在运行时分配内存。这些函数返回指向分配块的指针,程序员必须对其进行管理(使用 free 释放)。 |
| 函数指针 | 存储函数地址的指针。允许将函数作为参数传递给其他函数(回调),或存储在数据结构中。 |
这些概念建立在对指针声明、赋值和解引用的基本理解之上,并将在相关章节中更详细地探讨。