C语言指针知识详解

1. 指针是什么?

首先简单来说,指针就是存储内存地址的变量,所以其本质也就是一个变量用来存储,唯一区别是存储的内容不同。

在计算机内存中,每个字节都有一个唯一的地址,就像每个房间都有门牌号一样。指针变量存储的就是这个"门牌号",通过这个地址,我们可以直接访问和操作内存中的数据。

2. 指针的基本语法

2.1 指针的声明

指针的声明使用星号(*)运算符:

int *p; // 声明一个指向整型的指针 char *c; // 声明一个指向字符的指针 float *f; // 声明一个指向浮点数的指针 double *d; // 声明一个指向双精度浮点数的指针

需要注意的是对于正常的程序代码来说,不同的类型对应的字节数是:char--1字节、short--2字节、int--4字节、long--4字节、float--4字节、double--8字节。但是对应生成的指针变量的字节数是由对应的计算机系统的位数决定的:对于16位系统指针是2字节(2*8)、对于32位系统指针是4字节(4*8)、对于64位系统指针是8字节(8*8)。

2.2 取地址运算符(&)

取地址运算符用于获取变量的内存地址:

int num = 10; int *p; // 定义整型指针p p = # // 给p赋值num的首位的地址 // 另外的写法: int *p = # printf("num的地址:%p\n", &num); // 输出num的地址 printf("指针p的值:%p\n", p); // 输出指针p存储的地址

2.3 解引用运算符(*)

解引用运算符用于通过指针访问或修改其指向的值:

int num = 10; int *p = # printf("num的值:%d\n", num); // 输出:10 printf("*p的值:%d\n", *p); // 输出:10 *p = 20; // 通过指针修改num的值 printf("修改后num的值:%d\n", num); // 输出:20

3. 指针的常见用途

3.1 动态内存分配

指针是实现动态内存分配的关键:

// 动态分配内存 int *arr = (int*)malloc(10 * sizeof(int)); if (arr == NULL) { printf("内存分配失败!\n"); return 1; } // 使用动态数组 for (int i = 0; i < 10; i++) { arr[i] = i * 2; } // 释放内存 free(arr); arr = NULL; // 避免野指针

3.2 函数参数传递

通过指针可以实现函数参数的"传址调用":

// 交换两个整数的值 // 先传入x,y的地址,然后在函数内部进行对x,y的值的取值*,从而进行交换 void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } int main() { int x = 10, y = 20; printf("交换前:x=%d, y=%d\n", x, y); // 输出:10, 20 swap(&x, &y); printf("交换后:x=%d, y=%d\n", x, y); // 输出:20, 10 return 0; }

3.3 数组与指针的关系

数组名本质上是一个指向数组首元素的常量指针:

int arr[5] = {1, 2, 3, 4, 5}; // 以下两种访问方式是等价的 printf("arr[2] = %d\n", arr[2]); // 数组下标访问 printf("*(arr+2) = %d\n", *(arr+2)); // 指针算术运算

4. 指针的高级概念

函数指针

指向函数的指针,用于回调函数等高级编程技巧:

#include <stdio.h> int add(int a, int b) { return a + b; } int multiply(int a, int b) { return a * b; } int main() { // 1. 正确声明一个函数指针 func_ptr // 这个指针可以指向任何“返回 int 且接收两个 int 参数”的函数 int (*func_ptr)(int, int); // 2. 让指针指向 add 函数 func_ptr = add; // 通过函数指针进行调用 printf("10 + 20 = %d\n", func_ptr(10, 20)); // 输出:30 // 3. 让指针改指向 multiply 函数 func_ptr = multiply; // 再次调用 printf("10 * 20 = %d\n", func_ptr(10, 20)); // 输出:200 return 0; }