Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #81933 > unrolled thread
| Started by | Steve Keller <keller.steve@gmx.de> |
|---|---|
| First post | 2021-10-08 22:47 +0200 |
| Last post | 2021-10-09 17:40 +0000 |
| Articles | 5 on this page of 25 — 10 participants |
Back to article view | Back to comp.lang.c++
Global const objects missing from object file Steve Keller <keller.steve@gmx.de> - 2021-10-08 22:47 +0200
Re: Global const objects missing from object file red floyd <no.spam.here@its.invalid> - 2021-10-08 15:09 -0700
Re: Global const objects missing from object file Steve Keller <keller.steve@gmx.de> - 2021-10-10 08:28 +0200
Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-10 12:03 +0300
Re: Global const objects missing from object file David Brown <david.brown@hesbynett.no> - 2021-10-10 12:29 +0200
Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-09 10:47 +0300
Re: Global const objects missing from object file scott@slp53.sl.home (Scott Lurndal) - 2021-10-09 14:32 +0000
Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-09 21:39 +0300
Re: Global const objects missing from object file Steve Keller <keller.steve@gmx.de> - 2021-10-10 08:55 +0200
Re: Global const objects missing from object file Bo Persson <bo@bo-persson.se> - 2021-10-10 10:34 +0200
Re: Global const objects missing from object file Steve Keller <keller.steve@gmx.de> - 2021-10-10 15:55 +0200
Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-10 17:28 +0300
Re: Global const objects missing from object file Steve Keller <keller.steve@gmx.de> - 2021-10-10 20:42 +0200
Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-10 22:44 +0300
Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-10 12:14 +0300
Re: Global const objects missing from object file Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-10-29 06:29 -0700
Re: Global const objects missing from object file Bo Persson <bo@bo-persson.se> - 2021-10-29 15:55 +0200
Re: Global const objects missing from object file Öö Tiib <ootiib@hot.ee> - 2021-10-29 22:20 -0700
Re: Global const objects missing from object file Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-11-07 04:51 -0800
Re: Global const objects missing from object file scott@slp53.sl.home (Scott Lurndal) - 2021-10-29 14:44 +0000
Re: Global const objects missing from object file Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-11-07 05:08 -0800
Re: Global const objects missing from object file scott@slp53.sl.home (Scott Lurndal) - 2021-11-07 14:21 +0000
Re: Global const objects missing from object file David Brown <david.brown@hesbynett.no> - 2021-10-10 12:33 +0200
Re: Global const objects missing from object file "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2021-10-09 15:05 +0200
Re: Global const objects missing from object file Juha Nieminen <nospam@thanks.invalid> - 2021-10-09 17:40 +0000
Page 2 of 2 — ← Prev page 1 [2]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2021-11-07 05:08 -0800 |
| Message-ID | <86ilx4aza8.fsf@linuxsc.com> |
| In reply to | #82179 |
scott@slp53.sl.home (Scott Lurndal) writes:
> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Paavo Helde <myfirstname@osa.pri.ee> writes:
>>
>>> In some sense the do not differ. The const globals in C++ are
>>> primarily meant for replacing C #define. Each C #define is TU-specific
>>> and gets fully preprocessed by the preprocessor, no other TU-s are
>>> involved.
>>
>> It appears you have sidestepped the central question here. What a
>> definition like 'const int foo = 7;' (without any mention anywhere
>> of 'extern') does in C++ is, AFAICT, exactly the same as a similar
>> definition with static, namely 'static const int foo = 7;'.
>
> Is that not dependent upon scope? For example:
>
> class x {
> static const unsigned long FRED = 0xabcdef00ul;
>
> };
Yes, it's true that leaving off 'static' here means something
significantly different. Note however, (a) neither of these
forms is allowed in C so there is no question of incompatibility;
(b) the 'static'-less form wasn't allowed until C++11; (c) only
the 'static' form works for the purpose of being usable in
constant expressions, so the question here is moot.
> requires an additional declaration in a compilation unit, e.g.
>
> const unsigned long x::FRED;
In my tests such a declaration was needed only if the address of
the static member FRED was taken. (I confess I didn't even try
to consult the C++ standard to see if that result is officially
okay or is merely a consequence of undefined behavior.)
> While
>
> namespace y {
> const unsigned long FRED = 0xabcdef00ul;
> };
>
> doesn't require an additional declaration.
AFAICT declarations inside namespaces behave the same way as
declarations at file scope, that is, const-without-static
behaves just the same way as const-with-static (and the same
rules for declarations/definitions, etc). So I don't think
this scenario is an exception to what I said earlier.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2021-11-07 14:21 +0000 |
| Message-ID | <JhRhJ.65858$iq.35710@fx10.iad> |
| In reply to | #82260 |
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>scott@slp53.sl.home (Scott Lurndal) writes:
>
>> Is that not dependent upon scope? For example:
>>
>> class x {
>> static const unsigned long FRED = 0xabcdef00ul;
>>
>> };
>
>Yes, it's true that leaving off 'static' here means something
>significantly different. Note however, (a) neither of these
>forms is allowed in C so there is no question of incompatibility;
>(b) the 'static'-less form wasn't allowed until C++11; (c) only
>the 'static' form works for the purpose of being usable in
>constant expressions, so the question here is moot.
>
>> requires an additional declaration in a compilation unit, e.g.
>>
>> const unsigned long x::FRED;
>
>In my tests such a declaration was needed only if the address of
>the static member FRED was taken. (I confess I didn't even try
>to consult the C++ standard to see if that result is officially
>okay or is merely a consequence of undefined behavior.)
Actually, it depends more on context and the compilation options.
With gcc (on linux), if you compile with -O2 or -O3 (and do
not use the address operator), you don't need to add the
declaration. If you don't use -O, then you will likely find
the linker complaining about a missing symbol. I see this
quite regularly, to the point that we generally use enum for
constants (or const definitions in a namespace), even tho
enum (pre C++xx) doesn't lend itself to type safety.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-10-10 12:33 +0200 |
| Message-ID | <sjufig$ekt$1@dont-email.me> |
| In reply to | #81958 |
On 10/10/2021 08:55, Steve Keller wrote:
> Paavo Helde <myfirstname@osa.pri.ee> writes:
>
>> Such global const definitions normally appear in a common header file
>> and would just cause duplicate linker symbols if they had external
>> linkage. Now they can be just optimized away in translation units
>> which do not use them.
>>
>> I believe the original motivation was to have an easy replacement of C
>> macros in header files, i.e. instead of
>>
>> #define a 42
>>
>> one can easily use
>>
>> const int a = 42;
>>
>> which would function almost exactly like a #define, plus it honors C++
>> namespaces and cannot be undefined.
>
> If you write such "global" const objects into a header file they are
> in fact not global, because the implicit 'static' makes them local to
> file translation unit and this can even cause duplication:
>
> $ cat foo.hh
> const int a = 42;
>
> const int *bar();
> $ cat x.cc
> #include "foo.hh"
>
> const int *bar() { return &a; }
> $ cat y.cc
> #include <iostream>
>
> #include "foo.hh"
>
> const int *foo() { return &a; }
>
> int main()
> {
> std::cout << (void *)foo() << '\n' << (void *)bar() << '\n';
> }
> $ g++ -Os -o foo x.cc y.cc
> $ ./foo
> 0x56027d731008
> 0x56027d731004
>
> For a small 'int' one may not care but for larger constant objects
> this may be really bad.
>
> To avoid it, I think you still have to write the defintion into only
> one C++ source file using 'extern'
>
> extern const int = 42;
You don't (IMHO) want "extern" here - you want to make sure that this
file includes the header with the "extern const int a;" declaration.
(And you forgot the "a" in that line.)
>
> and put
>
> extern const int a;
>
> into the header file. I still don't see the advantage for C++ to
> differ from C here.
>
It is convenient when you have const objects defined within a file and
that are local to the file - there is no need for a "static". (A lot of
people are far too lazy about putting "static" where it is appropriate
in their C and C++ coding.)
With C++17, you can also write:
extern inline const int a = 42;
in the header, and you don't need a definition in a C++ file.
[toc] | [prev] | [next] | [standalone]
| From | "Alf P. Steinbach" <alf.p.steinbach@gmail.com> |
|---|---|
| Date | 2021-10-09 15:05 +0200 |
| Message-ID | <sjs428$165$1@dont-email.me> |
| In reply to | #81933 |
On 8 Oct 2021 22:47, Steve Keller wrote:
> I am surprised I cannot define a global const object in one file and
> access it in another:
>
> --------- x.cc ---------
> const int a = 42
Assuming the code actually has a semicolon here, so that it compiles.
Copy and paste code to avoid such typos.
> ------------------------
>
> --------- y.cc ---------
> extern const int a;
>
> int foo() { return a; }
> ------------------------
>
> When I compile both sources to objects I see access to 'a' as
> expected:
>
> movl a(%rip), %eax
> ret
>
> But the object file x.o does not contain anything. Why?
Because without `extern` the definition in `x.cpp` has internal linkage,
as noted by Red Floyd in his response.
And since it's not visible outside the translation unit, and is not used
within it, and its initialization has no side effects, it's optimized away.
> If I remove the 'const' in the definition and in the extern
> declaration it works as expected. Also if add an 'extern' to the
> definition in x.cc so that it is
>
> extern const int a = 42;
>
> the object 'a' is created in x.o. Can someone explain this?
See above.
A good way to avoid these problems is to place the declaration of `a`,
with an `extern`, in a header file that you include both in the defining
source file and in the using source file.
Because, when the compiler has seen the `extern`-ness of `a` once in a
translation unit, then in any subsequent encounter of `a` that
`extern`-ness is implied.
- Alf
[toc] | [prev] | [next] | [standalone]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2021-10-09 17:40 +0000 |
| Message-ID | <sjsk5p$v77$1@gioia.aioe.org> |
| In reply to | #81933 |
Steve Keller <keller.steve@gmx.de> wrote: > If I remove the 'const' in the definition and in the extern > declaration it works as expected. Also if add an 'extern' to the > definition in x.cc so that it is > > extern const int a = 42; > > the object 'a' is created in x.o. Can someone explain this? This is one key difference between C and C++. In C, const variables at the global namespace level have external linkage by default. In other words, they are implicitly 'extern'. In C++, const variables at the namespace level (including the global namespace) have internal linkage by default. In other words, they are implicitly 'static'. In C, if you want a const variable in the global namespace to have internal linkage, you need to explicitly specify 'static' in its declaration. In C++, if you want a const variable at a namespace level (including the global namespace) to have external linkage, you need to explicitly specify 'extern' in its declaration. (In C++ this is true for *any* type, not just basic types.) Previously this was a minor nuisance in C++ because a 'const' variable in a header would be duplicated in each object file that used it, if the compiler couldn't optimize it away (ie. "inline" it). If you wanted only one instance of that const variable, you had to 'extern' it manually. C++17 added support for "inline const" variables, which does this for you automatically (in the same way as 'inline' does with functions).
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.c++
csiph-web