【C语言】知识总结·指针篇

发布于:2025-06-28 ⋅ 阅读:(16) ⋅ 点赞:(0)

前言:

文接上章,在上章节中讲解一些基础函数,循环结构,以及数组,函数的调用。

指针

在 C 语言中,指针是一种极为重要的变量类型,它能够存储内存地址。借助指针,你可以直接对内存进行操作,实现如动态内存分配、传递引用参数等功能。下面将详细讲解 C 语言指针的相关知识。

一·概念

指针是一种变量,其存储的数值是内存地址,通过地址可以改变该地址上的数据


 

二·指针的声明 

数据类型 *指针变量名;
  • 数据类型:表明该指针所指向变量的数据类型。
  • *:用于声明这是一个指针变量。

int *p; // 声明一个指向整型的指针

float *q; // 声明一个指向浮点型的指针

char *str; // 声明一个指向字符型的指针 


 

三·指针的基本操作

1. 取地址运算符(&

&运算符能够获取变量的内存地址。

int num = 42;
int *p = #  // 将num的地址赋值给指针p

2. 解引用运算符(*

*运算符可以访问指针所指向内存地址中的值。

int num = 42;
int *p = #

printf("num的值:%d\n", num);      // 输出:42
printf("p指向的值:%d\n", *p);     // 输出:42(通过指针访问)
printf("p存储的地址:%p\n", (void*)p);  // 输出:num的内存地址

3.修改指针指向的值

int num = 42;
int *p = #

*p = 100;  // 修改指针所指向的值

printf("num的值:%d\n", num);  // 输出:100

四·指针与数组

在 C 语言里,数组名本质上就是数组首元素的地址,这使得指针和数组之间的关系十分紧密。

1.数组名作为指针 

int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;  // 等价于 int *p = &arr[0];

printf("arr[0] = %d\n", *p);       // 输出:1
printf("arr[1] = %d\n", *(p + 1));  // 输出:2(指针偏移)

2.指针算术运算

  • 指针加法(p + n:指针向后偏移n个元素的位置(偏移量为n * sizeof(数据类型))。
  • 指针减法(p - n:指针向前偏移n个元素的位置。
  • 指针自增 / 自减(p++p--:指针向后 / 向前偏移 1 个元素的位置。

例如

int arr[5] = {10, 20, 30, 40, 50};
int *p = arr;

printf("%d\n", *p);    // 输出:10
printf("%d\n", *(p+2));  // 输出:30(偏移2个元素)

 

 


五·指针作为函数参数

通过指针作为函数参数,可以实现对原始数据的修改(传址调用),还能避免数据的复制,提高效率。

 1. 传址调用示例:交换两个整数的值

#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5, y = 10;
    swap(&x, &y);  // 传递变量地址
    
    printf("x = %d, y = %d\n", x, y);  // 输出:x = 10, y = 5
    return 0;
}

2. 数组作为函数参数

数组作为函数参数传递时,会自动转换为指针。

void printArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);  // 等价于 *(arr + i)
    }
}

// 调用示例
int arr[5] = {1, 2, 3, 4, 5};
printArray(arr, 5);  // 输出:1 2 3 4 5

 六·指针与字符串

在 C 语言中,字符串通常用字符数组或字符指针来表示。

1. 字符串字面量与字符指针

char *str = "Hello";  // 字符串字面量存储在常量区
printf("%s\n", str);  // 输出:Hello

2. 字符数组与字符指针的区别

// 字符数组(可修改内容)

char str1[] = "Hello";
str1[0] = 'J';  // 合法:修改数组元素

// 字符指针(指向常量字符串,不可修改)

char *str2 = "Hello";
// str2[0] = 'J';  // 非法:修改常量字符串会导致运行时错误

 字符数组可修改,字符指针不可修改。

int  main()
{
    char str[] = "hello world";
    str[0] = 'w';
    printf("%s", str);
    return 0;
} 


七·指针数组与数组指针

1. 指针数组

指针数组是由多个指针组成的数组,其每个元素都是一个指针

 

int a = 10, b = 20, c = 30;
int *arr[3] = {&a, &b, &c};  // 指针数组

printf("%d\n", *arr[2]);  // 输出:10

 

2. 数组指针(指向数组的指针)

数组指针是指向整个数组的指针。

int arr[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &arr;  // 数组指针

printf("%d\n", (*p)[0]);  // 输出:1

八·函数指针

函数指针是指向函数的指针变量,通过它可以动态调用不同的函数。

#include <stdio.h>

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

int main() 
{
    // 声明函数指针
    int (*operation)(int, int);

    // 指向add函数
    operation = add;
    printf("5 + 3 = %d\n", operation(5, 3));  // 输出:8

    // 指向sub函数
    operation = sub;
    printf("5 - 3 = %d\n", operation(5, 3));  // 输出:2

    return 0;
}

 

 2. 函数指针作为参数

void calculate(int a, int b, int (*op)(int, int)) 
{
    printf("结果:%d\n", op(a, b));
}

// 调用示例
calculate(5, 3, add);  // 输出:8
calculate(5, 3, sub);  // 输出:2

九·多级指针

多级指针是指向指针的指针,最常见的是二级指针。

示例:二级指针

int x = 10;
int *p = &x;      // 一级指针
int **pp = &p;    // 二级指针(指向指针的指针)

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

十·常见的错误

1·未初始化指针:使用未初始化的指针会导致访问非法内存。

int *p;      // 声明一个整型指针p,但未初始化
*p = 10;     // 错误:对未初始化的指针解引用

正确的是

int num = 0;   // 定义一个整型变量
int *p = &num; // 让p指向num的地址
*p = 10;       // 正确:通过p修改num的值为10
printf("%d", num); // 输出:10

野指针:指针释放后未置为NULL,继续使用会导致问题。

int *p = (int*)malloc(sizeof(int));
free(p);
*p = 10;  // 错误:p已释放

总结

指针是C语言的重中之重,要多加练习,才能掌握。

难点较多,容易错误。

作用:

  • 直接操作内存,提供底层控制能力。
  • 高效传递数据,减少内存开销。
  • 构建复杂数据结构和实现高级编程技巧。