Как extern "C" влияет на линковку?

Подобно этому вопросу, я могу скомпилировать эту программу без необходимости включать hello.h в hello.cpp.
Но если я использую extern "C", то во время связывания я получаю неопределенную ссылку на hello в main.cpp. Почему это?

привет.hpp:

extern "C" void hello();

привет.cpp:

//#include "hello.h"
#include <stdio.h>

void hello() { 
    std::cout << "Hello!" << std::endl;
}

основной.cpp:

#include "hello.h"

int main() {
    hello();
    return 0;
}

g++ -c main.cpp hello.cpp
g++ main.o hello.o
main.cpp: undefined reference to 'hello'

Я не решаюсь сказать, что это точный дубликат, поскольку он, похоже, не дает прямого ответа на ваш конкретный вопрос, но может иметь для вас полезную информацию.

Chipster 01.07.2023 04:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

extern "C" удаляет украшение имени, которое большинство компиляторов применяют к именам функций C++. Если вы пытаетесь назвать неукрашенное имя, но у вас получилось только украшенное, они не найдут друг друга.

В обычных компоновщиках каждая функция (не локальная для объектного файла/библиотеки) должна иметь уникальное имя. В C все функции имеют уникальное имя (без перегрузки, без членства в классе и т. д.), поэтому оформление имени не требуется (и компилятор может использовать либо отсутствие оформления, либо фиксированную схему оформления, например, добавление _). C++ имеет перегрузку функций (две функции с одинаковыми именами и разными типами аргументов), и необходимо оформление, чтобы компоновщик видел каждую перегрузку как имеющую уникальное имя. extern "C" также может изменить механизм передачи аргументов и возврата значений.

Peter 01.07.2023 05:19

Итак, в моем случае, если бы я включил заголовочный файл в hello.cpp, спецификация компоновки применялась бы к объявлению функции (я забыл, что мне также не нужно использовать extern "C" в определении функции). Таким образом, неукрашенное имя, вызываемое в main и определенное в hello.cpp, совпадает, и связывание выполняется успешно.

Quaxton Hale 01.07.2023 05:25

Другие вопросы по теме