当前位置: 首页 > article >正文

【C语言】特殊指针汇总

前言

        C语言的指针有多种类型,除了常用的那几类之外我们还有多种特殊指针会使用到,接下来我会介绍一下四种特殊指针,特别是空指针和野指针,在实际的编程中会经常遇到。

空指针

        空指针(Null Pointer)是一种特殊的指针,它不指向任何有效的内存地址。在C语言中,空指针通常用于表示一个无效的指针。

        在C语言中,空指针可以通过以下方式定义:

int *ptr = NULL; // 使用NULL宏定义空指针

    NULL是一个宏,通常定义为((void*)0),表示一个空指针常量。 

常见用途

  1. 初始化指针:在声明指针时,将其初始化为空指针,以确保在后续代码中可以安全地检查和使用该指针。
  2. 动态内存分配失败处理:在动态内存分配(如使用malloccalloc等函数)时,如果分配失败,这些函数会返回空指针。这时需要检查并处理这种情况。
  3. 函数参数:在函数中使用指针作为参数时,可以使用空指针来表示某些特殊情况,比如没有数据或不需要传递数据。

注意事项

  • 避免解引用空指针:解引用空指针会导致未定义行为,通常会导致程序崩溃。因此,在使用指针之前一定要检查其是否为空。
  • 释放内存后置空:在释放动态分配的内存后,将指针置为空指针可以避免悬挂指针(Dangling Pointer)问题,即指针仍然指向已释放的内存区域。
  • 初始化指针:在声明指针时尽量将其初始化为空指针,这样可以确保在使用前进行有效性检查。

野指针

        野指针(Dangling Pointer)是指向没有初始化的指针,声明了一个指针但没有初始化它,导致它指向一个未知的内存地址。

代码示例

未初始化的指针
int *ptr; // 未初始化的指针
*ptr = 10; // 解引用未初始化的指针,会导致未定义行为

悬空指针

        悬空指针(Dangling Pointer)是指向已经被释放或无效内存地址的指针。在C语言中,悬空指针通常由以下几种情况引起:

  1. 释放后的指针:指针指向的内存已经被释放,但指针本身没有被置为空指针。
  2. 超出作用域的局部变量:指针指向一个已经超出其作用域的局部变量。
  3. 数组越界访问:指针指向数组的非法位置。

示例代码

释放后的指针
#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr = (int *)malloc(sizeof(int));
    if (ptr == NULL) {
        printf("Memory allocation failed.\n");
        return -1;
    }
    *ptr = 42;
    free(ptr); // 释放内存
    // 此时ptr成为悬空指针,因为它指向的内存已经被释放
    *ptr = 50; // 使用已释放的内存,会导致未定义行为
    return 0;
}
超出作用域的局部变量
#include <stdio.h>

void func() {
    int localVar = 10;
    int *ptr = &localVar; // 指向局部变量的指针
}

int main() {
    int *ptr;
    func();
    // ptr = &localVar; // 错误:localVar超出了作用域,ptr成为悬空指针
    return 0;
}
数组越界访问
#include <stdio.h>

void func() {
    int localVar = 10;
    int *ptr = &localVar; // 指向局部变量的指针
}

int main() {
    int *ptr;
    func();
    // ptr = &localVar; // 错误:localVar超出了作用域,ptr成为悬空指针
    return 0;
}
如何避免悬空指针
  • 避免返回局部变量的地址:确保指针不要指向已经销毁的局部变量。
  • 使用动态内存分配:如果需要返回指针,确保返回指向动态分配内存的指针,直到手动释放内存。

万能指针

        万能指针是指不指定指向数据类型的指针,它使用 void 类型来声明。void* 类型的指针可以指向任何类型的数据,但它不能直接解引用,因为没有具体的数据类型。


http://www.kler.cn/a/445607.html

相关文章:

  • OpenSSL 心脏滴血漏洞(CVE-2014-0160)
  • 【进阶编程】MVC和MVVM实现前后端分离的实现
  • 时间序列异常值检测方法
  • javax.net.ssl.SSLPeerUnverifiedException: Hostname 192.168.13.13 not verified:
  • OneCode:开启高效编程新时代——企业定制出码手册
  • Mac iOS、Android、Flutter、React Native开发环境配置
  • 【Ubuntu】截图软件flameshort
  • docker--压缩镜像和加载镜像
  • Go 语言常量
  • Webpack中Loader和Plugin的区别
  • 怎么利用Redis实现延时队列?
  • 机器智能能产生算计吗?
  • 分布式全文检索引擎ElasticSearch-数据的写入存储底层原理
  • C语言——实现百分制换算为等级分
  • 多模块的spring boot项目发布指定模块的脚本
  • 移动网络(2,3,4,5G)设备TCP通讯调试方法
  • SDMTSP:黑翅鸢算法(Black-winged kite algorithm,BKA)求解单仓库多旅行商问题,可以更改数据集和起点(MATLAB代码)
  • 企业健康采购市场:谁在成为优质供给的底层支撑?
  • 前端安全实践:常见攻击的防范与处理
  • 以前很常见的一种HTTP操作方式
  • 【进阶编程】MVC和MVVM实现前后端分离的实现
  • Springboot logback 日志打印配置文件,每个日志文件100M,之后滚动到下一个日志文件,日志保留30天(包含traceid)
  • 最短路径C++
  • 讲PPT 需要注意的事项
  • 单片机与MQTT协议
  • 计算机网络 - HTTP 协议和万维网