Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is it legal to return address of local string literal

18 views
Skip to first unread message

Mathias Nord

unread,
Apr 25, 2002, 4:12:30 AM4/25/02
to
Consider the following:

struct Test
{
static const char* name()
{
return "XYZ";
}
static const char* name2()
{
static const char n[] = "XYZ";
return n;
}
};

I know (?) that Test::name2() is both legal and portable but Test::name()
seems to work too. At least with VC++7 and some old version of gcc.

The question: Is Test::name() legal?

/Mathias

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Sebastian Kapfer

unread,
Apr 25, 2002, 9:04:29 AM4/25/02
to
On Thu, 25 Apr 2002 10:12:30 +0200, Mathias Nord wrote:

> Consider the following:
>
> struct Test
> {
> static const char* name()
> {
> return "XYZ";
> }
> static const char* name2()
> {
> static const char n[] = "XYZ";
> return n;
> }
> };
>
> I know (?) that Test::name2() is both legal and portable but
> Test::name() seems to work too. At least with VC++7 and some old version
> of gcc.
>
> The question: Is Test::name() legal?

Yes, it is. Pointers to string literals remain valid for the whole
execution time of a C++ program.

C++ standard, 2.13.4 (1): String literals [lex.string]
> An ordinary string literal has type "array of n const char" and static
> storage duration (3.7), [...].

3.7.1 (1): Static storage duration [basic.stc.static]
> All objects which neither have dynamic storage duration nor are local
> have static storage duration. The storage for these objects shall last
> for the duration of the program (3.6.2, 3.6.3).

HTH,
sk

Gennaro Prota

unread,
Apr 25, 2002, 9:12:34 AM4/25/02
to
On 25 Apr 2002 04:12:30 -0400, "Mathias Nord"
<mathi...@hotmail.com> wrote:

>Consider the following:
>
>struct Test
>{
> static const char* name()
> {
> return "XYZ";
> }
> static const char* name2()
> {
> static const char n[] = "XYZ";
> return n;
> }
>};
>
>I know (?) that Test::name2() is both legal and portable but Test::name()
>seems to work too. At least with VC++7 and some old version of gcc.
>
>The question: Is Test::name() legal?
>

Quite the contrary. Let me be a little pedantic, but I think it's
important to help understanding here. String-literals are not objects,
they are expressions that designate objects (therefore it's quite
improper to say "address of a string literal" :) Note BTW that they
are the only kind of literal that are l-values).

The object a string literal refers to (an array of const char or const
wchar_t) has always static duration (2.13.4).

Therefore Test::name is (thanks to array-to-pointer conversion)
perfectly right: it returns the address of the first element of an
array that remains undestroyed at function exit; Test::name2() returns
instead the address of n[0], which is a local array (initialized a
string literal).


Hope this helps,
Genny.

Giovanni Asproni

unread,
Apr 25, 2002, 9:15:09 AM4/25/02
to
Hi Mathias,
The answer to yoy question is yes. The string literal has type array of n
(where n is the number of characters included the '\0' ) const char, and has
static storage allocation (that is lasts for the entire life of the
program).
Cheers,
Giovanni

Attila Feher

unread,
Apr 25, 2002, 11:19:16 AM4/25/02
to
Mathias Nord wrote:
> struct Test
> {
> static const char* name()
> {
> return "XYZ";
> }
[SNIP]

> The question: Is Test::name() legal?

Yes it is. Why? You seem to mix up local variables with string
literals. The expression "XYZ" is a string literal. A string literal
(usually) gets memory allocated in some read-only memory area. So there
is only one XYZ, somewhere in the memory. When you write down this
"XYZ", into the code, it will "mean" the address of that (basically
static) memory area. And you return this address from Test::name().
You can test it yourself by calling Test::name() many times, from main,
from functions called from main (so that the "stack is moved") and print
the address. You will see, that the address is always the same. If you
know a bit more about your architecture, you may even find out, that
this address is in a read-only memory area (page, segment, whatever it
is called there).

Attila

James Kanze

unread,
Apr 25, 2002, 11:21:46 AM4/25/02
to
"Mathias Nord" <mathi...@hotmail.com> writes:

|> Consider the following:

|> struct Test
|> {
|> static const char* name()
|> {
|> return "XYZ";
|> }
|> static const char* name2()
|> {
|> static const char n[] = "XYZ";
|> return n;
|> }
|> };

|> I know (?) that Test::name2() is both legal and portable but
|> Test::name() seems to work too. At least with VC++7 and some old
|> version of gcc.

|> The question: Is Test::name() legal?

The question is, what is the difference in the two, other than the fact
that the second has a locally visible name?

The first is not only legal, I think it is the more frequent idiom. (It
is certainly more frequent in my code, and if it suddenly stopped
working, I'd have a lot of fixing to do.)

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

James Kanze

unread,
Apr 25, 2002, 4:41:12 PM4/25/02
to
Gennaro Prota <gennar...@yahoo.com> writes:

|> On 25 Apr 2002 04:12:30 -0400, "Mathias Nord"
|> <mathi...@hotmail.com> wrote:

|> >Consider the following:

|> >struct Test
|> >{
|> > static const char* name()
|> > {
|> > return "XYZ";
|> > }
|> > static const char* name2()
|> > {
|> > static const char n[] = "XYZ";
|> > return n;
|> > }
|> >};

|> >I know (?) that Test::name2() is both legal and portable but
|> >Test::name() seems to work too. At least with VC++7 and some old
|> >version of gcc.

|> >The question: Is Test::name() legal?

|> Quite the contrary. Let me be a little pedantic, but I think it's
|> important to help understanding here. String-literals are not
|> objects,

They most certainly are, although they are unnamed objects.

|> they are expressions that designate objects (therefore it's quite
|> improper to say "address of a string literal" :) Note BTW that they
|> are the only kind of literal that are l-values).

And anything which is an l-value must be an object, since its address
can be taken.

|> The object a string literal refers to (an array of const char or
|> const wchar_t) has always static duration (2.13.4).

More correctly, the string literal defines an unnamed array (an
object) of const char, with static duration, as you say. The length of
the array can be detected by such tricks as passing it to a template
function with a parameter char const (&x)[N], where N is a template
parameter.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Michiel Salters

unread,
Apr 25, 2002, 4:42:56 PM4/25/02
to
"Mathias Nord" <mathi...@hotmail.com> wrote in message
news:<aa742k$ee4$1...@green.tninet.se>...
> Consider the following: {SNIPPED}

> const char* name()
> {
> return "XYZ";
> }

Legal by (2.13.4):
"A[n]... string literal has ... static storage duration (3.7) "

HTH,
--
Michiel Salters

Gennaro Prota

unread,
Apr 25, 2002, 5:23:56 PM4/25/02
to

Oooops.... I didn't see the static keyword here:

> > static const char* name2()
> > {
> > static const char n[] = "XYZ";

^^^

so the answer is that both implementations are correct, sorry for my
oversight :(

Robert Monroe

unread,
Apr 25, 2002, 6:14:39 PM4/25/02
to
"Mathias Nord" <mathi...@hotmail.com> wrote in message news:<aa742k$ee4$1...@green.tninet.se>...
> Consider the following:
>
> struct Test
> {
> static const char* name()
> {
> return "XYZ";
> }
> static const char* name2()
> {
> static const char n[] = "XYZ";
> return n;
> }
> };
>
> I know (?) that Test::name2() is both legal and portable but Test::name()
> seems to work too. At least with VC++7 and some old version of gcc.
>
> The question: Is Test::name() legal?
>
Yes, it's legal. I do it fairly often. A string literal is different
from a local array in that the data is there for the life of the
program, in some data segment. When the string is used in an
expression it evaluates to an address that is always valid.

Bob.

Gennaro Prota

unread,
Apr 26, 2002, 3:44:54 AM4/26/02
to
On 25 Apr 2002 16:41:12 -0400, James Kanze <ka...@alex.gabi-soft.de>
wrote:

>Gennaro Prota <gennar...@yahoo.com> writes:
>
>|> String-literals are not objects,
>
>They most certainly are, although they are unnamed objects.
>
>|> they are expressions that designate objects (therefore it's quite
>|> improper to say "address of a string literal" :) Note BTW that they
>|> are the only kind of literal that are l-values).
>
>And anything which is an l-value must be an object, since its address
>can be taken.

An l-value is an expression to me (3.10p1). It *refers* to an object,
is not a C++ object by itself.


>|> The object a string literal refers to (an array of const char or
>|> const wchar_t) has always static duration (2.13.4).
>
>More correctly, the string literal defines an unnamed array (an
>object) of const char, with static duration, as you say.

Yes, the array is unnamed (the string-literal itself is not an
identifier, so its use is not a name) but in what does this differ
from what I said? The only difference I can detect depends on your
wording "the string literal defines", but you are not saying that the
use of a string literal is a definition, are you? (And BTW you first
say it is an object then that it *defines* an object, so I can't see
your point)

I'm quite surprised by this reply, since I consider you one of my
teachers here :(((

Genny.

Allan W

unread,
Apr 26, 2002, 10:50:21 AM4/26/02
to
Gennaro Prota <gennar...@yahoo.com> wrote

> On 25 Apr 2002 04:12:30 -0400, "Mathias Nord"
> <mathi...@hotmail.com> wrote:
>
> >Consider the following:
> >
> >struct Test
> >{
> > static const char* name()
> > {
> > return "XYZ";
> > }
> > static const char* name2()
> > {
> > static const char n[] = "XYZ";
> > return n;
> > }
> >};
> >
> >I know (?) that Test::name2() is both legal and portable but Test::name()
> >seems to work too. At least with VC++7 and some old version of gcc.
> >
> >The question: Is Test::name() legal?
> >
>
> Quite the contrary. Let me be a little pedantic, but I think it's
> important to help understanding here. String-literals are not objects,
> they are expressions that designate objects (therefore it's quite
> improper to say "address of a string literal" :) Note BTW that they
> are the only kind of literal that are l-values).
>
> The object a string literal refers to (an array of const char or const
> wchar_t) has always static duration (2.13.4).
>
> Therefore Test::name is (thanks to array-to-pointer conversion)
> perfectly right: it returns the address of the first element of an
> array that remains undestroyed at function exit; Test::name2() returns
> instead the address of n[0], which is a local array (initialized a
> string literal).

What you write is true -- n[] is an array initialized by a string
literal. However, you imply that name2() is not legal because it
returns the address of a local variable. n[] is declared static,
so name2() is legal.

However, your point that name() returns the data directly while
name2() has to copy it the first time it's called, is perfectly true.
This also implies that name2() could have returned a non-const
pointer -- and if it did, the caller could have modified the data in
n[]. This would be illegal for name(), although I believe that no
diagnostic is required.

Attila Feher

unread,
Apr 26, 2002, 10:52:40 AM4/26/02
to
James Kanze wrote:
[SNIP]

> |> they are expressions that designate objects (therefore it's quite
> |> improper to say "address of a string literal" :) Note BTW that they
> |> are the only kind of literal that are l-values).
>
> And anything which is an l-value must be an object, since its address
> can be taken.

Well, since it is unnamed...:

According to K&R II (page 197): [1]

"An _object_ is a named region of storage; an _lvalue_ is an
expression referring to an object."

So it cannot be unnamed, to be an lvalue...

Attila

James Kanze

unread,
Apr 27, 2002, 7:51:32 AM4/27/02
to
Gennaro Prota <gennar...@yahoo.com> writes:

|> On 25 Apr 2002 16:41:12 -0400, James Kanze <ka...@alex.gabi-soft.de>
|> wrote:

|> >Gennaro Prota <gennar...@yahoo.com> writes:

|> >|> String-literals are not objects,

|> >They most certainly are, although they are unnamed objects.

|> >|> they are expressions that designate objects (therefore it's
|> >|> quite improper to say "address of a string literal" :) Note
|> >|> BTW that they are the only kind of literal that are l-values).

|> >And anything which is an l-value must be an object, since its
|> >address can be taken.

|> An l-value is an expression to me (3.10p1). It *refers* to an
|> object, is not a C++ object by itself.

Right. I seem to have skipped a few steps. A string literal causes
an object to be created, and refers to that object.

I think what bothered me was the bald statement that they are not
objects, and that it is improper to speak of their address. While the
string literal itself is not formally an object, it is quite usual (I
think) to use the term to refer to the actual object it causes to be
created, and I, for one, do talk about the address of string literals.
And of course, the expression &"abc", is legal, and has the type
"pointer to array[4] of const char".

|> >|> The object a string literal refers to (an array of const char
|> >|> or const wchar_t) has always static duration (2.13.4).

|> >More correctly, the string literal defines an unnamed array (an
|> >object) of const char, with static duration, as you say.

|> Yes, the array is unnamed (the string-literal itself is not an
|> identifier, so its use is not a name) but in what does this differ
|> from what I said? The only difference I can detect depends on your
|> wording "the string literal defines", but you are not saying that
|> the use of a string literal is a definition, are you? (And BTW you
|> first say it is an object then that it *defines* an object, so I
|> can't see your point)

Careless wording?

I found your first paragraph misleading, since there very definitly is
an object involved, with an implicit definition, static memory
allocation, an address, etc. But perhaps I just read it wrong.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

James Kanze

unread,
Apr 29, 2002, 11:21:33 AM4/29/02
to
Attila Feher <Attila...@lmf.ericsson.se> writes:

|> James Kanze wrote:
|> [SNIP]
|> > |> they are expressions that designate objects (therefore it's
|> > |> quite improper to say "address of a string literal" :) Note
|> > |> BTW that they are the only kind of literal that are
|> > |> l-values).

|> > And anything which is an l-value must be an object, since its
|> > address can be taken.

|> Well, since it is unnamed...:

|> According to K&R II (page 197): [1]

|> "An _object_ is a named region of storage; an _lvalue_ is an
|> expression referring to an object."

|> So it cannot be unnamed, to be an lvalue...

According to the standard (5.1/2): "A string literal is an lvalue; all
other literals are rvalues." In C (which is the language K&R write
about), we also have (6.5.1/4) "A string literal is a primary
expression. It is an lvalue with type as detailed in 6.4.5."
Standardese is sometimes difficult to understand, but I don't see how
these phrases could possibly cause a problem. And string literals
definitly don't refer to named objects.

I suspect that Kernighan and Richie just overlooked the case.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Gennaro Prota

unread,
May 1, 2002, 5:26:05 PM5/1/02
to
On 27 Apr 2002 07:51:32 -0400, James Kanze <ka...@alex.gabi-soft.de>
wrote:

> A string literal causes an object to be created, and refers to that object.

Not necessarily every literal I think: due to 2.13.4p2 a compiler can
reuse (part of) an object already created for another literal. Do you
agree?

>I found your first paragraph misleading, since there very definitly is
>an object involved, with an implicit definition, static memory
>allocation, an address, etc. But perhaps I just read it wrong.

In fact, my intent was exactly to reassure the original poster that
*there is* an object somewhere even if it isn't explictly declared in
his code and that, therefore, the situation is (thanks to 2.13.4 and
5.1p2) completely different from, let's say:

const int& f() { return 3; }


Genny.

James Kanze

unread,
May 2, 2002, 5:32:38 PM5/2/02
to
Gennaro Prota <gennar...@yahoo.com> writes:

|> On 27 Apr 2002 07:51:32 -0400, James Kanze <ka...@alex.gabi-soft.de>
|> wrote:

|> > A string literal causes an object to be created, and refers to
|> > that object.

|> Not necessarily every literal I think: due to 2.13.4p2 a compiler
|> can reuse (part of) an object already created for another literal.
|> Do you agree?

Yes. But there is still an object.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(0)179 2607481

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

0 new messages