📕
innohub
  • KEEP LEARNING
  • WebInfo
    • JS 部分运算符操作
    • javascript 中的object array
    • 错误处理以及异常捕获
    • JavaScript Bases
    • LaoZi & Confucius
  • PyInfo
    • Python3 输入与输出
    • Python3OS
    • python 修饰器的使用
    • python3 与mysql数据库连接使用实例
    • Format-specifier
    • CGI初学踩坑
    • Django 项目测试
    • Assert-info
    • 使用ngnix和uWSGI配置Django
    • write|SVN​
    • Matplotlib 基本使用
    • 重读 Python 官方文档
    • Python3 Base
    • python3 多线程
    • Python3 函数解析
    • python3 str 对象的基本操作
    • protocl buffers
    • Iterator-Generator
    • Django base
    • Decorator 2
    • Export to wheel or egg-info
    • 三. 运算、数据及逻辑
  • GoInfo
    • Info
      • Select 语句使用
      • First class function
      • Work Pools
      • StructTag
      • Go struct
      • 常用函数
      • Strings操作
      • Golang Bases
      • 数组以及切片
      • 文件操作
      • Golang 中的指针类型
      • Golang Map 类型
      • Reflection
      • 函数闭包
      • 接口
      • Panic and Recover
      • Go中的错误处理
      • 并发
      • defer usage
      • Method in golang
      • Object-oriented Programming
      • Goalng 包管理机制
  • RustInfo
    • Info
      • 包、crate、模块
      • Rust 中的错误处理
      • 智能指针
      • 泛型 generics
      • 数据布局与内存对齐
      • Functions and methods
      • 无畏并发
      • Actix-web 基本使用
      • Got from guessing game
      • 结构体的使用
      • Rust 中的函数式语言功能
      • 集合类型
      • 枚举以及模式匹配
      • Slice 类型
      • 生命周期
      • 测试
      • Rust 中的所有权
      • trait
      • 不安全 Rust
      • Format_print
      • Rust 通用编程概念
      • Macro
  • OS
    • info
      • 内存屏障 -- Part 1
      • 内存屏障 -- Part 2
      • CPU 上下文切换
      • 文件读写与零拷贝
      • ELF 文件
  • MySql
    • info
      • MySql 架构与历史
      • 02-key
  • kubernetes
    • 第二章 k8s 基本概念
    • 第一章 Kubernetes -- 伟大舵手
  • Redis
    • info
      • Redis 总览
      • 02-underline-ds
  • Shell&CInfo
    • GCC 与make的使用
    • C++ 中 malloc 与 new
    • 位运算符操作
    • Base of C macro
    • C 语言中 extern 关键字的用法
  • Distributed
    • info
      • 分布式理论概述
  • Java
    • info
      • Java 内存模型
  • Prometheus
    • Prometheus -- 不灭之火
Powered by GitBook
On this page
  • 概述
  • :one: 在一个文件内声明的外部变量
  • :two: 在多个文件中声明外部变量

Was this helpful?

  1. Shell&CInfo

C 语言中 extern 关键字的用法

[TOC]

概述

​ extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。

​ 就是说extern有两个作用,第一个,当它与"C"一起连用时,如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非,可能是fun@aBc_int_int#%$也可能是别的,这要看编译器的"脾气"了(不同的编译器采用的方法不一样),为什么这么做呢,因为C++支持函数的重载啊,在这里不去过多的论述这个问题,如果你有兴趣可以去网上搜索,相信你可以得到满意的解释!

​ 第二,当extern不与"C"在一起修饰变量或函数时,如在头文件中: extern int g_Int; 它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块活其他模块中使用,记住它是一个声明不是定义!也就是说B模块(编译单元)要是引用模块(编译单元)A中定义的全局变量或函数时,它只要包含A模块的头文件即可,在编译阶段,模块B虽然找不到该函数或变量,但它不会报错,它会在连接时从模块A生成的目标代码中找到此函数。

:one: 在一个文件内声明的外部变量

可以使用extern关键字声明外部变量,外部变量是指在函数或者文件外部定义的全局变量,其定义必须在作用域之外,而且仅可声明一次。可以在函数内部使用extern关键字指明所需要使用的外部变量

#include <stdio.h>

int max(int x, int y); // 函数提前声明
int main(int argc, char *argv[])
{
    int result;
    extern int X;
    extern int Y;
    result = max(X, Y);
    printf("the max value is %d\n", result);
    return 0;
}

int X = 10; //定义外部变量
int Y = 20;

int max(int x, int y)
{
    return (x > y ? x : y);
}

:two: 在多个文件中声明外部变量

如果整个工程中有多个文件在一个文件中需要引用另一个文件中的变量,只需要使用extern关键字将其作用域扩展到整个项目

文件 a.c 的内容

#include <stdio.h>
int BASE = 2;
extern int exe(int x);

int main(int argc, char *argv[])
{
    int a = 10;
    printf("%d^%d = %d\n", BASE, a, exe(a));
    return 0;
}

文件 b.c 的内容

#include <stdio.h>
extern BASE; // 声明的外部变量
int exe(int x)
{
    int i;
    int ret = 1;
    for (i = 0; i < x; i++) {
        ret *= BASE;
    }

    return ret;
}

​ 对于多个文件的工程,可以采用这种方法来操作。实际工程中,对于模块化的程序文件,在其文件中可以预先留好外部变量的接口,也就是只采用 extern 声明变量,不定义变量,也通常在模块程序的头文件中声明,在使用该模块时,只需要在使用时定义一下即可,如上述 b.c 文件,做好相应的函数接口,留好需要改变 BASE 值的声明,在需要使用该模块时,只需要在需要调用的文件中定义具体的值即可。

​ 引用外部变量和通过函数形参值传递变量的区别:用extern 引用外部变量,可以在引用的模块内修改其值,而形参值传递的变量则不能修改其值,除非是地址传递。 因此,如果多个文件同时对需要应用的变量进行同时操作,可能会修改该变量,类似于形参的地址传递,从而影响其他模块的使用,因此要慎重的使用。

PreviousBase of C macroNextDistributed

Last updated 5 years ago

Was this helpful?