【C语言】指针的基本用法及语法规范

【C语言】指针的基本用法及语法规范

文章目录

前言

一、指针是什么?

二、指针用法及规范

1.基本指针语法

2.指针数组与数组指针

3.函数指针

4.常量指针与指针常量

5.函数参数与返回值

6.typedef与指针

7.动态内存管理

8.代码风格建议

总结

前言

本文详细讲解 C 语言中指针的概念、声明方式以及正确使用方法

一、指针是什么?

指针是 C 语言中一种特殊的变量,它存储的是其他变量的内存地址。指针让程序可以直接操作内存,从而实现高效的数据传递和灵活的数据结构管理。

二、指针用法及规范

1.基本指针语法

标准写法(推荐写法):星号(*)紧贴变量名,明确表示该变量是指针:

int *p; // p 是指向 int 的指针

类型后写法:星号(*)可紧贴类型名,但需注意编译器视角:星号(*)实际绑定的是变量名而非类型。

int* p; // 合法,但注意多变量声明时的陷阱

多变量声明:如果在同一行声明多个变量,必须对每个指针变量都加上 *

int *p, *q; // 正确:p 和 q 都是 int* 类型

int* p, q; // 错误:仅 p 为指针,q 为普通 int

指针初始化:未初始化的指针(野指针)指向未知内存,直接解引用可能导致程序崩溃

// 正确示范

int x = 5;

int *p = &x; // 指向变量 x

int *q = NULL; // 初始化为空指针

// 错误示范

int *p; // 未初始化的野指针

*p = 10; // 崩溃风险极高

多级指针:多级指针即指针的指针,常用于需要多重间接访问的场景

int x = 10;

int *p = &x; // 一级指针

int **pp = &p; // 二级指针

printf("%d", **pp); // 输出 10

2.指针数组与数组指针

指针数组:指针数组是一个数组,数组中的每个元素都是指针。由于数组下标 []的优先级高于 *,下面的声明表示数组内元素为指针

int *arr[5]; // 定义一个包含 5 个 int* 的数组

// 可定义一个包含若干整数地址的数组

int a = 1, b = 2, c = 3;

int *ptr_arr[3] = {&a, &b, &c};

数组指针:数组指针则是一个指针,指向一个数组(整个数组的首地址)。为避免优先级混淆,需要使用括号明确表示指针绑定的是变量,而非类型

int (*ptr)[5]; // ptr 是指向包含 5 个 int 的数组的指针

// 处理二维数组

int matrix[3][4] = {0}; // 3 行 4 列的二维数组

int (*p)[4] = matrix; // p 指向一个含 4 个 int 的一维数组

// 通过函数参数传递二维数组时:

void print_matrix(int (*mat)[4], int rows) {

for (int i = 0; i < rows; i++) {

for (int j = 0; j < 4; j++) {

printf("%d ", mat[i][j]);

}

printf("\n");

}

}

3.函数指针

基本语法:函数指针允许将函数作为参数传递或返回,函数指针声明时(*)必须被括号包裹,后面紧跟参数列表。

int (*func_ptr)(int, int); // func_ptr 是指向接受两个 int 参数并返回 int 的函数的指针

int *func(int, int); // 错误:声明了一个返回 int* 的函数

回调函数

// 回调函数 compare 用于排序比较

int compare(int a, int b) {

return a - b;

}

void sort(int *arr, int size, int (*compare)(int, int)) {

// 简化示例:假设排序实现调用 compare 比较数组元素

}

int main() {

int data[] = {5, 2, 9};

sort(data, 3, compare);

return 0;

}

4.常量指针与指针常量

常量指针:指向常量的指针,指针所指向的数据不能通过该指针修改,但指针本身可以指向其他地址。

const int *p = &x; // 或写作 int const *p;

// *p = 10; // 错误,不能通过 p 修改 *p 的值

p = &y; // 正确,可以改变 p 的指向

指针常量:指针本身是常量,一旦初始化后就不能再改变指向的地址,但可以修改所指数据的值。

int *const p = &x;

*p = 10; // 正确,可以修改 x 的值

// p = &y; // 错误,不能改变 p 的指向

指向常量的指针常量:指针和所指向的数据都不可修改

const int *const p = &x;

// *p = 10; // 错误,不能修改数据

// p = &y; // 错误,不能改变指向

5.函数参数与返回值

作为函数参数:

(1)传递变量地址

void modifyValue(int *p) {

*p = 20;

}

int main() {

int a = 10;

modifyValue(&a);

printf("%d\n", a); // 输出 20

return 0;

}

(2)传递数组指针(数组首地址)

void modifyArray(int *arr, int size) {

for (int i = 0; i < size; i++) {

arr[i]++; // 每个元素加 1

}

}

int main() {

int nums[] = {1, 2, 3};

modifyArray(nums, 3);

return 0;

}

(3)传递只读数据

// 传入常量指针

void printArray(const int *arr, int size) {

for (int i = 0; i < size; i++) {

printf("%d ", arr[i]);

}

}

作为函数返回值:

错误示范:返回局部变量地址

int *createValue() {

int x = 100;

return &x; // 错误:x 是局部变量,函数返回后内存无效

}

正确示范:使用动态内存分配

int *createValue() {

int *p = malloc(sizeof(int));

if (p) {

*p = 100;

}

return p;

}

int main() {

int *p = createValue();

if (p) {

printf("%d\n", *p);

free(p);

p = NULL;

}

return 0;

}

6.typedef与指针

使用typedef 可以简化复杂指针的声明,使代码更易读

typedef定义指针类型

typedef int* IntPtr;

IntPtr p1, p2; // p1 和 p2 都是 int* 类型

// 注意与int* p, q; 中 q 变为 int 的区别

typedef与函数指针

typedef int (*FuncPtr)(int, int);

int add(int a, int b) { return a + b; }

FuncPtr f = add;

typedef与结构体指针

typedef struct Node {

int data;

struct Node *next;

} Node, *NodePtr;

7.动态内存管理

int main() {

int *arr = malloc(5 * sizeof(int));

if (!arr) {

perror("Memory allocation failed");

exit(1);

}

// 使用 arr...

free(arr); // 释放内存

arr = NULL; // 避免悬空指针

return 0;

}

8.代码风格建议

指针声明风格

int* p; // 推荐(指针和 `int*` 绑定)

int *p1, *p2; // 避免 `int *p1, p2;` 误解

对于不应修改的数据,使用const 限制

void printData(const int *data);

避免内存泄漏

free(ptr);

ptr = NULL; // 避免 `free()` 之后的悬空指针

对于固定常量,使用 #define 或 typedef,增加代码可维护性

#define MAX_SIZE 100

typedef unsigned char byte;

总结

本文从指针的基本概念出发,详细介绍了指针的声明、指针数组与数组指针、函数指针、常量指针及其在函数参数和返回值中的应用。同时,还讨论了使用typedef简化复杂指针声明、动态内存管理的正确方法,以及代码风格和最佳实践。希望通过这些内容,能帮助你写出更安全、可读和高效的 C 语言代码。

通过不断实践和积累经验,你会发现指针既强大又灵活,祝你在 C 语言的学习和编程中不断进步!

相关推荐

视频如何消音处理?6个适合新手的简单方法,可批量操作
微信收藏的文件在手机哪个文件夹?教你轻松找到位置
7k7k找轮胎小游戏
365bet娱乐投注

7k7k找轮胎小游戏

📅 07-01 👁️ 2735