zoukankan      html  css  js  c++  java
  • externn "C"解析

    1.揭密extern "C"

    extern "C"包含双重含义,从字面上即可得到:首先,被它修饰的目标是 "extern”的;其次,被它修饰的目标是 "C”的。
    首先来看一下 "extern”的含义
    a.在一个文件内,如果外部变量不在文件的开头定义,其有效范围只限定在定义到文件的结束处。如果在定义前需要引用该变量,则要在引用之前用关键字 "extern” 对该变量做“外部变量声明”,表示该变量是一个已经定义的外部变量。有个这个声明,就可以从声明处起合理地使用该变量了。"extern”起到了扩展作用域的作用。

    复制代码
    //.c
    #include <stdio.h>
    void main()
    {
        extern A;//用extern声明外部变量;若变量为int类型,类型名可写也可以省略。
        printf("%d", A);
    }
    int A=100;
    复制代码

    b.在多文件的程序中,如果多个文件都要使用同一个外部变量,不能在各个文件中各定义一个外部变量,否则会出现“重复定义”的错误。正确的做法是:在任一个文件中定义外部变量,其他文件用 "extern”对变量做“外部变量声明”。在编译和连接时,系统会由此知道该变量是一个已经在别处定义的外部变量,并把另一文件中外部变量的作用域扩展到本文件,这样在本文件就可以合法地使用该外部变量了。

    复制代码
    //file1.c
    #include <stdio.h>
    int A = 100;//定义外部变量
    void main()
    {
        printf("%d",power());
    }
    
    //file2.c
    extern A;//声明A为一个已定义的外部变量
    int power()
    {
        return A*A;
    }
    复制代码

    extern只用作声明,而不用于定义。extern说明变量或者函数定义在其他的源文件里,而不用include头文件的方式来引用该函数,在链接时,链接器在各个模块中搜索这个变量或者函数来进行最终链接。
    c.外部函数
    在定义函数时,如果在最左端加关键字extern,表示此函数是外部函数。C语言规定,如果在定义时省略extern,则隐含为外部函数。而内部函数必须前加static关键字;
    在需要调用此函数的文件中,用extern对函数作声明,表示该函数是在其他文件中定义的外部函数。
    "C”的含义:(extern “C”)
    C++通过函数参数的不同类型支持重载机制,编译器根据参数为每个重载函数产生不同的内部标识符。例如编译器为void Eat(Beef …);void Eat(Fish …);void Eat(Chicken …);三个Eat 函数产生象_eat_beef、_eat_fish、_eat_chicken 之类的内部标识符(不同的编译器可能产生不同风格的内部标识符)。
    如果 C++程序要调用已经被编译后的C 函数,该怎么办?
    假设某个 C 函数的声明如下:

    void foo(int x, int y);

    该函数被C 编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字用来支持函数重载和类型安全连接。由于编译后的名字不同,C++程序不能直接调用C 函数。C++提供了一个C连接交换指定符号extern“C”来解决这个问题。
    例如:

    复制代码
    extern “C”
    {
    void foo(int x, int y);
    … // 其它函数
    }
    或者写成
    extern “C”
    {
    #include “myheader.h”
    … // 其它C 头文件
    }
    复制代码

    这就告诉C++编译译器,函数foo 是个C 连接,应该到库中找名字_foo 而不是找_foo_int_int。C++编译器开发商已经对C 标准库的头文件作了extern“C”处理,所以我们可以用#include 直接引用这些头文件。

    2.extern "C"程序实例

    假设有C文件:

    复制代码
    //c.h
    #ifndef _C_H_
    #define _C_H_
    
    extern int add(int x, int y);
    
    #endif
    复制代码
    //c.c
    int add(int x, int y)
    {
        return x+y;
    }

    在C++下调用add()函数

    复制代码
    //cplusplus.cpp
    #include <iostream>
    #include "c.h"
    using namespace std;
    void main()
    {
        add(1, 0);
        system("Pause");
    }
    复制代码

    产生错误:无法解析的外部符号 "int __cdecl add(int,int)" (?add@@YAHHH@Z),该符号在函数 _main 中被引用
    为了解决这个问题,我们需要使用extern "C"。改写C文件

    复制代码
    //c.h
    #ifndef _C_H_
    #define _C_H_
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    extern int add(int x, int y);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    复制代码

    文件为*.c,__cplusplus没有被定义,extern "C" {}这时没有生效,对于C语言只是extern int add(int, int);而编译c++源文件,__cplusplus被定义,对于C++他看到的是extern "C" {extern int add(int, int);},编译器就会知道add(1, 0)调用的是C连接。
    最后:很多DLL的生成文件(XXX.c)中常出现extern "C" ,windows采用C语言编译创建dll,C程序可以正确调用DLL,而当用户使用C++调用DLL时,extern "C" {}就起作用了。

    转自:extern "C"的简单解析 - 侯凯 - 博客园
    http://www.cnblogs.com/houkai/archive/2013/06/05/3118807.html

  • 相关阅读:
    Codeforces Round 546 (Div. 2)
    Codeforces Round 545 (Div. 2)
    Codeforces Round 544(Div. 3)
    牛客小白月赛12
    Codeforces Round 261(Div. 2)
    Codeforces Round 260(Div. 2)
    Codeforces Round 259(Div. 2)
    Codeforces Round 258(Div. 2)
    Codeforces Round 257 (Div. 2)
    《A First Course in Probability》-chaper5-连续型随机变量-随机变量函数的分布
  • 原文地址:https://www.cnblogs.com/johnleo/p/extern_c.html
Copyright © 2011-2022 走看看