# 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关键字指明所需要使用的外部变量

```cpp
#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 的内容

```cpp
#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 的内容

```cpp
#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 引用外部变量，可以在引用的模块内修改其值，而形参值传递的变量则不能修改其值，除非是地址传递。 因此，如果多个文件同时对需要应用的变量进行同时操作，可能会修改该变量，类似于形参的地址传递，从而影响其他模块的使用，因此要慎重的使用。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://books.innohub.top/shell-and-cinfo/extern-of-c.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
