Última atualização:2026-10-12
O especificador de ligação extern em C++¶
Sobre o autor:¶
Conta oficial do WeChat:

1.Diferenças de compilação entre C++ e C¶
Em C++, é comum ver a expressão extern "C" modificando funções em arquivos de cabeçalho; qual é a sua função? Ela serve para o C++ vincular funções definidas em módulos escritos em linguagem C.
Embora o C++ seja compatível com C, os símbolos gerados após a compilação de funções em arquivos C++ são diferentes dos gerados pela linguagem C. Como o C++ suporta sobrecarga de funções, os símbolos gerados na compilação de funções C++ carregam informações sobre os tipos dos parâmetros da função, o que não ocorre em C.
Por exemplo, depois que a função int add(int a, int b) passa pelo compilador C++ gerando um arquivo .o, add se torna algo como add_int_int; em C, seria algo como _add. Ou seja: a mesma função, em C e em C++, gera símbolos diferentes após a compilação.
Isso provoca um problema: se o C++ usar funções implementadas em linguagem C, ocorrerá um erro na compilação/vinculação, dizendo que o símbolo correspondente não foi encontrado. É aqui que extern "C" entra em ação: ele diz ao vinculador para procurar símbolos da linguagem C, como _add, e não os símbolos decorados pelo C++.
2.C++ chamando funções C¶
Exemplo de C++ chamando uma função C: ao referenciar o arquivo de cabeçalho C, é preciso adicionar extern "C"
//add.h
#ifndef ADD_H
#define ADD_H
int add(int x,int y);
#endif
//add.c
#include "add.h"
int add(int x,int y) {
return x+y;
}
//add.cpp
#include <iostream>
#include "add.h"
using namespace std;
int main() {
add(2,3);
return 0;
}
Compilar:
Vincular:
Sem adicionar extern "C", ocorre o erro:
> g++ add.cpp add.o -o main
add.o:在函数‘main’中:
add.cpp:(.text+0x0): `main'被多次定义
/tmp/ccH65yQF.o:add.cpp:(.text+0x0):第一次在此定义
/tmp/ccH65yQF.o:在函数‘main’中:
add.cpp:(.text+0xf):对‘add(int, int)’未定义的引用
add.o:在函数‘main’中:
add.cpp:(.text+0xf):对‘add(int, int)’未定义的引用
collect2: error: ld returned 1 exit status
Após adicionar extern "C":
add.cpp
#include <iostream>
using namespace std;
extern "C" {
#include "add.h"
}
int main() {
std::cout << add(2, 3) << std::endl;
return 0;
}
Na compilação, atenção: primeiro gere o arquivo intermediário add.o com o gcc.
Depois compile:
Se usar o bazel para compilar, execute: bazel run basic_content/extern/extern_c++:main
E, para que o código C seja genérico, ou seja, possa ser chamado tanto por C quanto por C++, o arquivo de cabeçalho normalmente é escrito assim:
Assim, quando o C++ chama essa interface, ele a chama como uma interface C. Essa abordagem dispensa o extern C adicional por parte de quem usa C++, e os arquivos de cabeçalho da biblioteca padrão costumam fazer algo semelhante; caso contrário, por que você consegue usar diretamente as funções C de stdio.h sem precisar de extern C?
O código-fonte dos casos acima está em:
2.C chamando funções C++¶
extern "C" é um erro de sintaxe em C; ele deve ficar no arquivo de cabeçalho C++.
// add.h
#ifndef ADD_H
#define ADD_H
extern "C" {
int add(int x,int y);
}
#endif
// add.cpp
#include "add.h"
int add(int x,int y) {
return x+y;
}
// add.c
extern int add(int x,int y);
int main() {
add(2,3);
return 0;
}
Compilar:
Vincular:
O código-fonte dos casos acima está em:
Em resumo, concluímos o método de uso: nos arquivos de cabeçalho da linguagem C, as funções externas só podem ser especificadas como extern; a linguagem C não suporta a declaração extern "C", e incluir extern "C" em um arquivo .c gera erro de sintaxe na compilação. Por isso, todo extern "C" deve ficar nos arquivos relacionados ao programa cpp ou em seus cabeçalhos.
Concluímos as seguintes formas:
(1) C++ chamando funções C:
(2) C chamando funções C++
Contudo, diferente do C++ chamar interfaces C — o que de fato funciona com funções C já compiladas —, aqui o C chamando C++ nada mais é do que compilar o código C++ como se fosse código C e então chamá-lo. Ou seja, o C não consegue chamar diretamente funções de biblioteca C++.
Tópicos relacionados¶
- Funções virtuais puras e classes abstratas em C++ | C++那些事
- Asserções com assert em C++ | C++那些事
- Bit fields em C++ | C++那些事
- Implementando polimorfismo de C++ em linguagem C | C++那些事
- Constantes e modificadores com const em C++ | C++那些事
- A família completa do const em C++ | C++那些事
- O operador de desreferência * em C++ | C++那些事
- Inicialização e atribuição em C++ | C++那些事
- Formas de retornar múltiplos valores em C++ | C++那些事
- A palavra-chave mutable em C++ | C++那些事