#c #compilation #linker #extern
#c #Сборник #компоновщик #внешний
Вопрос:
Прошу прощения, если об этом спрашивали раньше. Я искал в Интернете и не нашел ответа.
Допустим, у меня есть файл Common.h
, и A.cpp
и B.cpp
включить Common.h
.
Если я хочу иметь глобальную const char *
в Common
единице перевода, я должен сделать это extern
в Common.h
и определить в Common.cpp
. В противном случае, если я просто определяю const char * MSG = "Hello World";
в Common.h
, я получаю duplicate symbol
ошибку во время компиляции.
Однако, если я просто определяю глобальный const int в Common.h
с помощью инструкции типа const int CONSTANT = 10;
, тогда код компилируется без ошибки повторяющегося символа, и все работает нормально.
Я не понимаю, почему это так. Мне кажется, что единственное различие между двумя приведенными выше примерами заключается в типе, который, я думаю, не должен иметь значения. Почему я получаю ошибку дублирования символа для C-строк, но не целых чисел?
Предположим, main.cpp
, A.h
B.h
A.cpp
и B.cpp
выглядят следующим образом:
// A.h
#pragma once
void f();
// A.cpp
#include "A.h"
#include "Common.h"
#include <iostream>
void f() {
std::cout << MSG << std::endl;
}
// B.h
#pragma once
void g();
// B.cpp
#include "B.h"
#include "Common.h"
#include <iostream>
void g() {
std::cout << CONSTANT << std::endl;
}
// main.cpp
#include "A.h"
#include "B.h"
int main()
{
f();
g();
}
Теперь предположим, что мы выполняем компиляцию с помощью команды g main.cpp A.cpp B.cpp Common.cpp -std=c 14
.
Если мы сделаем Common.h
и Common.cpp
следующее, то компиляция завершится ошибкой duplicate symbol MSG
:
// Common.h
#pragma once
const char * MSG = "Hello World";
const int CONSTANT = 10; // defined in header file
// Common.cpp
// empty
Однако это компилирует:
// Common.h
#pragma once
extern const char * MSG;
const int CONSTANT = 10; // defined in header file
// Common.cpp
#include "Common.h"
const char * MSG = "Hello World";
Мне интересно, зачем нам нужен extern и разделять определение и объявление для строки, но не для int.
Кто-то предложил сделать тип C-string as const char * const
вместо const char *
. Почему создание указателя const работает? Кроме того, в этом случае, в чем разница между этим решением и решением, которое я предоставил выше (где вместо этого мы создаем строку extern и разделяем определение / объявление)? Почему оба метода устраняют ошибку компиляции и в чем разница между этими методами?
Я также заметил, что если я превращаюсь const int
в just int
, то снова получаю duplicate symbol
ошибку. Я чувствую, что причина этого связана с ответом на мои вопросы выше. Почему это так?
Комментарии:
1. Ничто так не описывает код, как хорошо написанный код.
2.
const char *MSG
означает вызываемую неконстантную переменнуюMSG
.const
является частью указанного типа .3. пожалуйста, не помечайте несвязанные языки. C и C — разные языки с разными правилами. ваша программа, похоже, написана на C
4. @chux-ReinstateMonica Я предоставил код
5. @AnttiHaapala Концепции, о которых я спрашиваю, применимы как к C, так и к C
Ответ №1:
Это одно из различий C и C .
В C const
переменная является неявной static
, то есть видимой только для текущей единицы перевода. В C это неявно extern
так заметно для всей программы (что также является значением по умолчанию для других неконстантных деклараций как в C, так и в C ).
Это объясняет ваше наблюдение.
Примечание: const char *p
Объявление переменной не является const
переменной. Это означает, что он указывает на переменную const (т. е. *p
не может быть изменен), но p
сам по себе не является const
. Итак, поведение здесь другое. const char * const p
было бы объявлением const.
Комментарии:
1. Это имеет смысл. Отвечает на все мои вопросы выше. Спасибо!