I am looking for a graceful way to declare a string const that is to be
visible across many files.
If I do this:
//----hdr.h
const char * sFoo = "foo";
//file.cpp
#include <hdr.h>
strcpy(string, sFoo);
//anotherfile.cpp
#include <hdr.h>
strcpy(string, sFoo);
The linker complains that sFoo is multiply defined.
I don't want to use a #define as it breaks type safety. I don't want to have
multiple copies of '
const char * sFoo = "foo";' littering my code.
What is the most compact and maintainable way to do this?
RDeW
|
|
0
|
|
|
|
Reply
|
riley.dewiley (26)
|
8/26/2005 7:34:53 PM |
|
Riley DeWiley wrote:
> I am looking for a graceful way to declare a string const that is to be
> visible across many files.
>
> If I do this:
>
[snip example]
>
> The linker complains that sFoo is multiply defined.
>
> I don't want to use a #define as it breaks type safety. I don't want to
> have multiple copies of '
> const char * sFoo = "foo";' littering my code.
>
> What is the most compact and maintainable way to do this?
>
> RDeW
Header file:
extern const char sFoo[];
In (one) source file (exactly which doesn't matter):
const char sFoo[] = "foo";
--
λz.λi.i(i((λn.λm.λz.λi.nz(λq.mqi))((λn.λz.λi.n(nzi)i)(λz.λi.i(((λn.λz.λi.n
(nzi)i)(λz.λi.i(iz)))zi)))((λn.λz.λi.n(nzi)i)(λz.λi.i(iz)))zi))
|
|
0
|
|
|
|
Reply
|
bdonlan2 (53)
|
8/26/2005 7:39:53 PM
|
|
Riley DeWiley wrote:
> I am looking for a graceful way to declare a string const that is to be
> visible across many files.
>
> If I do this:
>
> //----hdr.h
>
> const char * sFoo = "foo";
>
> //file.cpp
> #include <hdr.h>
>
> strcpy(string, sFoo);
>
>
> //anotherfile.cpp
> #include <hdr.h>
>
> strcpy(string, sFoo);
>
>
> The linker complains that sFoo is multiply defined.
>
> I don't want to use a #define as it breaks type safety. I don't want to have
> multiple copies of '
> const char * sFoo = "foo";' littering my code.
>
> What is the most compact and maintainable way to do this?
If you declare it in the header
const char * const sFoo = "foo";
which creates multiple copies. To avoid that you could do
extern const char sFoo[];
in the header and in _one_of_the_C++_source_files_ do
extern const char sFoo[] = "foo";
The linker will be happy and you will have the only definition of the
string in the program.
V
|
|
0
|
|
|
|
Reply
|
v.Abazarov (13255)
|
8/26/2005 7:46:19 PM
|
|
Riley DeWiley wrote:
>
> I don't want to use a #define as it breaks type safety.
No, it doesn't.
#define sFoo "foo"
Every place you use the identifier sFoo you'll get a string literal. Its
type, however, is array of const char rather than pointer to const char,
which is what your code uses.
> I don't want to have
> multiple copies of '
> const char * sFoo = "foo";' littering my code.
>
> What is the most compact and maintainable way to do this?
>
In the header:
const char *sFoo;
In one implementation file:
const char *sFoo = "foo";
The suggestion the other messages make, to use const char sFoo[], also
works, but just like the macro, it makes sFoo a different type from what
you asked for.
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
|
|
0
|
|
|
|
Reply
|
petebecker (1324)
|
8/26/2005 8:14:59 PM
|
|
Pete Becker wrote:
> Riley DeWiley wrote:
>>
>> I don't want to use a #define as it breaks type safety.
>
> No, it doesn't.
>
> #define sFoo "foo"
>
> Every place you use the identifier sFoo you'll get a string literal. Its
> type, however, is array of const char rather than pointer to const char,
> which is what your code uses.
>
>> I don't want to have
>> multiple copies of '
>> const char * sFoo = "foo";' littering my code.
>>
>> What is the most compact and maintainable way to do this?
>>
>
> In the header:
> const char *sFoo;
>
> In one implementation file:
> const char *sFoo = "foo";
This is wrong. The first will create a pointer, initialized to NULL, in each
file it's included in. The second will create yet another pointer,
initialized to pointing to the constant string needed.
>
> The suggestion the other messages make, to use const char sFoo[], also
> works, but just like the macro, it makes sFoo a different type from what
> you asked for.
The array will automatically cast into const char * when needed, so it
doesn't matter.
--
λz.λi.i(i((λn.λm.λz.λi.nz(λq.mqi))((λn.λz.λi.n(nzi)i)(λz.λi.i(((λn.λz.λi.n
(nzi)i)(λz.λi.i(iz)))zi)))((λn.λz.λi.n(nzi)i)(λz.λi.i(iz)))zi))
|
|
0
|
|
|
|
Reply
|
bdonlan2 (53)
|
8/26/2005 11:26:33 PM
|
|
Victor Bazarov wrote:
> Riley DeWiley wrote:
> > I am looking for a graceful way to declare a string const that is to be
> > visible across many files.
> >
> > If I do this:
> >
> > //----hdr.h
> >
> > const char * sFoo = "foo";
> >
> > //file.cpp
> > #include <hdr.h>
> >
> > strcpy(string, sFoo);
> >
> >
> > //anotherfile.cpp
> > #include <hdr.h>
> >
> > strcpy(string, sFoo);
> >
> >
> > The linker complains that sFoo is multiply defined.
> >
> > I don't want to use a #define as it breaks type safety. I don't want to have
> > multiple copies of '
> > const char * sFoo = "foo";' littering my code.
> >
> > What is the most compact and maintainable way to do this?
>
> If you declare it in the header
>
> const char * const sFoo = "foo";
>
> which creates multiple copies. To avoid that you could do
>
> extern const char sFoo[];
>
> in the header and in _one_of_the_C++_source_files_ do
>
> extern const char sFoo[] = "foo";
>
> The linker will be happy and you will have the only definition of the
> string in the program.
>
> V
Const declarations by default have internal linkage, so the declaration
can remain in the header file once it's changed from a pointer to an
array. No source files need to be changed.
In other words change this declaration in the header file:
const char * const sFoo = "foo";
to this:
const char const sFoo[] = "foo";
And the multiple definition error will be fixed - no matter how many
source files actually include sFoo's declaration.
Greg
|
|
0
|
|
|
|
Reply
|
greghe (676)
|
8/27/2005 6:08:50 AM
|
|
Bryan Donlan wrote:
> Pete Becker wrote:
>
>
>>
>>>I don't want to have
>>>multiple copies of '
>>>const char * sFoo = "foo";' littering my code.
>>>
>>>What is the most compact and maintainable way to do this?
>>>
>>
>>In the header:
>>const char *sFoo;
>>
>>In one implementation file:
>>const char *sFoo = "foo";
>
>
> This is wrong. The first will create a pointer, initialized to NULL, in each
> file it's included in.
You're right: it needs an extern in front.
>
>
>>The suggestion the other messages make, to use const char sFoo[], also
>>works, but just like the macro, it makes sFoo a different type from what
>>you asked for.
>
>
> The array will automatically cast into const char * when needed, so it
> doesn't matter.
>
First, a cast is something you write in your code to tell the compiler
that you want a conversion. Second, there are two contexts in which the
conversion from array into pointer to its first element is not done. The
two types are not the same.
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
|
|
0
|
|
|
|
Reply
|
petebecker (1324)
|
8/27/2005 6:30:08 PM
|
|
Pete Becker wrote:
>
> Second, there are two contexts in which the
> conversion from array into pointer to its first element is not done. The
> two types are not the same.
>
Actually, that's true in C. In C++ there are more. And, in both
languages, this is not a conversion, but a decay: the name of an array
decays into a pointer to its first element in most contexts. And, of
course, it is still true that the two types are not the same. Try this:
a.c
---
char text[] = "abcd";
void f()
{
puts(text);
}
b.c
---
extern char *text;
void f();
int main()
{
*text = 'e';
f();
return 0;
}
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
|
|
0
|
|
|
|
Reply
|
petebecker (1324)
|
8/27/2005 8:29:13 PM
|
|
Riley DeWiley <riley.dewiley@gmail.com> wrote:
> I am looking for a graceful way to declare a string const that is to be
> visible across many files.
>
> If I do this:
>
> //----hdr.h
>
> const char * sFoo = "foo";
>
> //file.cpp
> #include <hdr.h>
>
> strcpy(string, sFoo);
>
>
> //anotherfile.cpp
> #include <hdr.h>
>
> strcpy(string, sFoo);
>
>
> The linker complains that sFoo is multiply defined.
>
> I don't want to use a #define as it breaks type safety. I don't want to have
> multiple copies of '
> const char * sFoo = "foo";' littering my code.
>
> What is the most compact and maintainable way to do this?
Would an #include guard work?
//-----hdr.h
#ifndef HDR_H
#define HDR_H
const char* sFoo = "foo";
#endif
--
Marcus Kwok
|
|
0
|
|
|
|
Reply
|
ricecake (206)
|
9/20/2005 3:49:33 PM
|
|
Riley DeWiley <riley.dewiley@gmail.com> wrote:
>>I am looking for a graceful way to declare a string const that is to be
>>visible across many files.
[...]
>>What is the most compact and maintainable way to do this?
Probably not the most compact way, but I suppose it would fit into the
maintainable and correct categories.
//--- MagicString.h
#ifndef MAGIC_STRING_H__
#define MAGIC_STRING_H__
extern const char* const gMagicString;
#endif
//--- MagicString.cpp
#include "MagicString.h"
const char* const gMagicString = "I am a magic string!";
//--- test.cpp
#include "MagicString.h"
#include <iostream>
int main()
{
std::cout << gMagicString << '\n';
}
Regards,
--
Ney Andr� de Mello Zunino
|
|
0
|
|
|
|
Reply
|
zunino2 (84)
|
9/20/2005 7:35:04 PM
|
|
Just a reminder on your include guards: words with double underscores
are reserved for the implemention.
|
|
0
|
|
|
|
Reply
|
mpinto70 (54)
|
9/20/2005 8:46:18 PM
|
|
Marcelo Pinto <mpinto70@gmail.com> schrieb:
> Just a reminder on your include guards: words with double underscores
.... at the beginning ...
> are reserved for the implemention.
Regards, Markus
|
|
0
|
|
|
|
Reply
|
yetispamb (62)
|
9/25/2005 2:10:34 PM
|
|
Markus Becker wrote:
> Marcelo Pinto <mpinto70@gmail.com> schrieb:
>> Just a reminder on your include guards: words with double underscores
>
> ... at the beginning ...
Nope: double underscores are off limits regardless of their position within
identifiers. See [17.4.3.1.2/1]:
17.4.3.1.2 Global names [lib.global.names]
1 Certain sets of names and function signatures are always reserved
to the implementation:
? Each name that contains a double underscore (__) or begins with
an underscore followed by an uppercase letter (2.11) is reserved
to the implementation for any use.
>> are reserved for the implemention.
Best
Kai-Uwe Bux
|
|
0
|
|
|
|
Reply
|
jkherciueh (3186)
|
9/25/2005 2:28:20 PM
|
|
|
12 Replies
21 Views
(page loaded in 0.273 seconds)
|