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

C extern在函数声明中的作用

1-1 extern关键字


这个关键字是用于外部的声明和引用的,主要是用于声明一个文件定义的全局变量可以在外部的文件中被引用,对于函数声明中这个关键字的作用实际上是默认存在的,写或者是不写编译器默认是存在extern这个关键字的,这种编写函数声明的方式在大型的代码项目中得到广泛的应用。


首先,我应该回顾一下C语言的基础知识。在C语言中,函数的声明默认是extern的,也就是说,即使不写extern,函数声明也默认具有外部链接属性。所以,在函数声明前显式地加上extern可能并不是必须的,但有时候程序员为了代码的可读性,可能会明确写出extern,以强调这个函数是在其他源文件中定义的。


根据C标准,函数的声明默认就是extern,所以显式添加可能只是编码风格的问题,或者为了强调。而变量的情况不同,全局变量如果要在多个文件中使用,必须使用extern来声明,否则会导致重复定义。所以,对于函数来说,extern是可选的,但通常不写,而对于变量则必须写。


1-2 详细说明


对于函数声明而言,extern 是默认隐含的(即使不写,编译器也会自动视为外部链接)

extern void F_Dsp_Seg(U8* buf);  // 显式声明
void F_Dsp_Signal(U8 state);     // 隐式声明(与上一行等价)

两种写法完全等价,加不加 extern 均可。实际编码中,函数声明通常省略 extern【建议加上去】


1-3 extern编写原因


代码可读性:明确强调"此函数由外部模块实现",尤其在大型项目中,帮助开发者快速理解函数来源。

与变量声明风格统一:某些团队规范要求所有外部符号显式标注 extern,保持代码一致性。

历史习惯:早期 C 标准对默认行为的规范不如现在清晰,老代码可能保留这一习惯。


1-4 extern真实的价值


与函数不同,全局变量的声明必须严格区分 extern(声明)和非 extern(定义):

// File1.c
int global_var = 42;  // ✅ 定义(分配内存)

// File2.c
extern int global_var;  // ✅ 声明(不分配内存,仅引用)

如果省略 extern 会导致重复定义: 

// File2.c
int global_var;  // ❌ 错误!与 File1.c 中的定义冲突

1-5 使用优点


  • 模块化开发
    允许将函数/变量定义集中在某一源文件(.c),通过头文件(.h)中的 extern 声明共享给其他模块。

  • 避免重复定义
    确保头文件中的声明不会意外创建新的变量实例(对变量尤为重要)。

  • 跨文件可见性控制

配合 static 关键字,可以精细控制符号的暴露范围:

  • static 函数/变量:仅在当前文件可见(内部链接)
  • extern 函数/变量:全局可见(外部链接)

1-6 使用建议


函数声明:可省略 extern,除非团队规范明确要求。

变量声明:在头文件中必须extern 声明全局变量,并在某一源文件中给出定义。

头文件保护:始终配合 #ifndef#pragma once 防止多次包含。


1-7 使用场景


├── display.h    // 声明函数
├── display.c    // 实现函数
└── main.c       // 使用函数

display.h 内容:

#pragma once

// 函数声明(extern 可省略但显式写出)
extern void F_Dsp_Seg(U8* buf);  
extern void F_Dsp_Signal(U8 state);

display.c 内容:

#include "display.h"

// 函数实际实现
void F_Dsp_Seg(U8* buf) { /* ... */ }
void F_Dsp_Signal(U8 state) { /* ... */ }

main.c内容 :

#include "display.h"  // 通过 extern 声明获得函数信息

int main() {
    U8 buffer[10];
    F_Dsp_Seg(buffer);  // 正确链接到 display.c 中的实现
    return 0;
}

通过这种组织方式,编译器在编译 main.c 时知道 F_Dsp_Seg 的存在,而链接器最终将 main.c 中的调用与 display.c 中的实现关联起来。

相关文章:

  • 各类数据质量等相关学习地址
  • vmware centos 10 stream boot 安装
  • 【算法】快排-786. 第k个数
  • 23. AI-大语言模型-DeepSeek
  • MySQL登录问题总结
  • 【Reasoning】LLaMA-Berry: Pairwise Optimization for O1-like Olympiad-Level Mathematical Reasoning
  • Linux 内核中的 container_of 宏:以 ipoib_rx_poll_rss 函数为例
  • Langchain vs. LlamaIndex:哪个在集成MongoDB并分析资产负债表时效果更好?
  • android,flutter 混合开发,pigeon通信,传参
  • RDMA ibverbs_API功能说明
  • 【蓝桥杯集训·每日一题2025】 AcWing 6122. 农夫约翰的奶酪块 python
  • Rust编程语言入门教程(五)猜数游戏:生成、比较神秘数字并进行多次猜测
  • javaSE学习笔记22-线程(thread)-线程通信、线程池
  • MySQL(1)基础篇
  • 【数据集】 jsonl格式
  • Rust编程语言入门教程 (六)变量与可变性
  • RTSP协议讲解及漏洞挖掘
  • 如何使用Redis实现分布式锁
  • ok113i平台——更改根目录分区大小
  • 【Linux】Linux 文件系统——剖析文件权限概念,文件类型和inode号
  • 案件发回重审,李在明参选韩总统之路再添波折
  • 杨轶群任莆田市荔城区人民政府副区长
  • 澎湃回声丨23岁小伙“被精神病”8年续:今日将被移出“重精”管理系统
  • 解放日报:这是一场需要定力和实力的“科技长征”
  • 铁路五一假期运输今日启动,预计发送旅客1.44亿人次
  • 直播电商行业代表呼吁:携手并肩伸出援手助力外贸企业攻坚克难