Why is extern required for const int but not for const char*
Asked Answered
D

1

6

I'm confused about why I need extern or not for int vs char* in the definition in my extern.cpp file. I have the following test program:

// extern.cpp
extern const int my_int = 1;
const char* my_str = "FOO";
// main.cpp
#include <iostream>

extern const int my_int;
extern const char* my_str;

int main() {
  std::cout << my_int;
  std::cout << my_str;
  return 0;
}

If I remove the extern from extern const int my_int = 1; then I get undefined reference to 'my_int'. If I add extern to const char* my_str = "FOO"; then I get a warning 'my_str' initialized and declared 'extern'. Why do I need extern on my_int but adding it to my_str generates a warning?

This is C++17 on gcc 10.1.0. The specific commands are:

/usr/bin/g++-10  -g -std=gnu++17 -o main.cpp.o -c main.cpp
/usr/bin/g++-10  -g -std=gnu++17 -o extern.cpp.o -c extern.cpp
/usr/bin/g++-10  -g main.cpp.o extern.cpp.o -o TestExtern
Dunstable answered 20/1, 2021 at 16:25 Comment(8)
my_str is not constAdolfoadolph
Does this answer your question? When to use extern in C++Visakhapatnam
I was wrong actually @Trovor explains why const has issue with externTaintless
extern is never intended to be used with initialization. Use extern in header files and then in some c or cpp file define the actual variable, without using extern. The extern declaration from the header file can be in scope and its types will have to match.Coonhound
So if you change my_str to const char * const my_str then you will have the same issue.Taintless
Not sure the duplicate is good. This question is really about a misunderstanding of const not about extern.Dissonance
@Dissonance there is an answer provided by Trovor which address exactly this issueTaintless
@Taintless Not really because I think the OP misunderstanding is about the meaning of const when applied to a pointer. But Andrey deals with this point below, so I guess it doesn't matter.Dissonance
S
12

This is caused by different linkage of my_int and my_str variables.

my_int is a const-qualified variable in namespace scope, which means it has internal linkage by default. In other words, its visibility is limited to the current translation unit, unless you mark it extern. Additionally, internal linkage constants must have an initializer.

my_str, on the other hand, is not const-qualified. Don't be confused by the const qualifier in the pointer type, as that qualifier is part of the pointed type. The pointer itself is mutable, and you could assign it a different value in run time. Since this is a non-const variable in namespace scope, it has external linkage, and as such refers to a single pointer object in the scope of the whole program.

Seedman answered 20/1, 2021 at 16:37 Comment(7)
You've got your internal linkage a bit wrong. Constants are not necessarily internal. You can declare an extern const int but don't try to set it to anything. That will create a linker reference to the actual definition of the const int. It will not be able to inline the const int into the code unless you use LTO but it will be able to reference it via its memory location.Coonhound
@ZanLynx I've updated the wording. I was talking about constants not explicitly marked as extern.Seedman
This is also important: https://mcmap.net/q/17193/-what-does-39-const-static-39-mean-in-c-and-cUptrend
This is a great reason to write char const * instead. It's the same type, but makes it clearer that the pointed-to value is what is const. The syntax const X should IMO never be used. const always goes to the right of the part of the type it applies to; it's allowed on the left in some cases for historical reasons, but this creates confusion. In this case the example types would be int const and char const * and now we can much more clearly see that the pointer value is not const because const is not the last token in the type.Tradeswoman
@cdho west const worst const east const best constAbigail
@Yakk-AdamNevraumont One const, two const, red const, blue const.Tradeswoman
@Tradeswoman unfortunately there are already too many bad habits in C++ from C. Constants in UPPERCASE, const is usually placed wrong place, * binds to variable not to type etc.Taintless

© 2022 - 2024 — McMap. All rights reserved.