天天看点

深入学习C语言:指针易错点剖析

作者:嵌入式讲堂

指针是C语言中非常重要的概念,也是C语言区别于其他语言的重要特性之一。但是,指针的使用也是C语言中最容易出现错误的地方。在编写程序时,如果不小心使用指针,可能会导致程序崩溃或产生其他未知错误。本篇文章将从十个常见的指针易错点入手,详细剖析指针的使用问题,帮助读者更深入地理解指针的使用。

目录

  • 空指针问题
  • 野指针问题
  • 非法指针问题
  • 悬空指针问题
  • 数组越界问题
  • 算术指针问题
  • 内存泄漏问题
  • 多级指针问题
  • 指针类型不匹配问题
  • 指针引用问题

空指针问题

指针未初始化或被赋为NULL时,会导致访问空指针而出现错误。例如:

int *p;
*p = 10; // p为未初始化的指针,会导致错误           

解决方法:在使用指针之前,一定要先将其初始化或赋为NULL。

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

野指针问题

指针被释放后,没有将其赋为NULL,继续使用该指针时会产生野指针问题。例如:

int *p = (int *)malloc(sizeof(int));
free(p);
*p = 10; // p为野指针,会导致错误           

解决方法:在释放指针后,一定要将其赋为NULL。

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

非法指针问题

指针未指向有效的内存地址时会出现非法指针问题。例如:

int *p = (int *)0x12345678;
*p = 10; // p为非法指针,会导致错误           

解决方法:在使用指针之前,一定要确保其指向有效的内存地址。

int a = 10;
int *p = &a;           

悬空指针问题

在函数中定义一个局部指针变量,并在函数结束后返回指向该指针指向的内存空间时,该指针变量就变成了悬空指针。例如:

int *func() {
    int a = 10;
    int *p = &a;
    return p;
}

int *p = func();
*p = 20; // p为悬空指针,会导致错误           

解决方法:尽量避免使用悬空指针。

int *func() {
    int *p = (int *)malloc(sizeof(int));
    *p = 10;
    return p;
}

int *p = func();
*p = 20;
free(p);           

数组越界问题

指针指向的地址超出数组范围,访问非法内存区域,并有可能导致程序崩溃。例如:

int a[10];
int *p = a + 20;
*p = 10; // p超出数组范围,会导致错误           

解决方法:在使用指针访问数组元素时,一定要确保指针指向的地址在数组范围内。

int a[10];
int *p = a + 5;
*p = 10;           

算术指针问题

当指针进行指针运算时,需要确保结果仍然指向合法的内存地址。例如:

int a[10];
int *p = a + 5;
int *q = p + 10; // q超出数组范围,会导致错误           

解决方法:在进行指针运算时,一定要确保结果仍然指向合法的内存地址。

int a[10];
int *p = a + 5;
int *q = p + 2;           

内存泄漏问题

在使用malloc等动态内存分配函数时,必须及时使用free函数释放分配的内存,否则会导致内存泄漏。例如:

int *p = (int *)malloc(sizeof(int));
*p = 10;
// 没有使用free函数释放p指向的内存空间,会导致内存泄漏           

解决方法:在使用malloc等动态内存分配函数分配内存空间后,一定要及时使用free函数释放内存空间。

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

多级指针问题

多级指针在使用时需要特别注意,容易造成混淆。例如:

int a = 10;
int *p = &a;
int **q = &p;
int ***r = &q;
printf("%d\n", ***r); // 输出10           

解决方法:在使用多级指针时,一定要注意指针的层数和指针指向的数据类型。

int a = 10;
int *p = &a;
int **q = &p;
int ***r = &q;
*q = (int *)malloc(sizeof(int));
**q = 20;
printf("%d\n", ***r); // 输出20
free(*q);           

指针类型不匹配问题

指针类型不匹配时会导致数据类型不匹配及其他错误。例如:

int a = 10;
float *p = &a; // p指向的类型与a的类型不匹配,会导致错误           

解决方法:在使用指针时,一定要确保指针指向的类型与所指向的变量类型匹配。

int a = 10;
int *p = &a;           

指针引用问题

指针引用时需要特别注意指针符号的使用和位置,容易产生混淆和错误。指针符号"*"有两种用法,一是用于声明指针类型,二是用于指针引用。下面是一个指针引用的例子:

int a = 10;
int *p = &a;
int b = *p; // *p表示取p指向的值,而不是取p的值           

在以上代码中,变量b的值是10,因为*p表示取p指向的值,即取a的值。如果代码中将“*p”写成“p”,则会发生编译错误。因此,在使用指针引用时,一定要注意指针符号的使用和位置。

int a = 10;
int *p = &a;
int b = p; // error: invalid conversion from ‘int*’ to ‘int’           

总之,指针是C语言中较为重要的部分,也是难点之一。使用指针时需时刻保持警惕,注意指针的初始化、释放、避免指针的错位等。读者如果能够深入地理解指针,掌握其中的注意点,那么写出高效且健壮的程序并不是难事。

难题

以下是一道面试题:

#include <stdio.h>

void change(int* a, int b){
    int *c = &b;
    a = c;
}

int main(){
    int a = 5;
    int b = 10;
    int *p = &a;
    change(p, b);
    printf("%d\n", *p);
    return 0;
}           

以上代码的输出结果是什么?为什么?请在评论区留言讨论。

继续阅读