Taking address of struct temporary

N

nroberts

I've been playing around with an object library and have run into an
inconsistency between using it under a C compiler and using it under a
C++ compiler.

I wanted a way to declare "objects" statically, meaning they exist as
constants. I did something like the following:

struct Object {
struct Class const* isa;
};

struct String_ {
struct Object const _;
char const* buf;
int len;
};

extern void* __X_STR;

#define xstr(X) &(struct String_){ { __X_STR }, X, sizeof(X) };

The '__X_STR' variable is defined statically in a C file.

Later I can do the following:

void* s = xstr("Hello World!);

This works fine under gcc but pitches a fit under g++ about taking the
address of a temporary.

In C++ the expression (struct String_)... is in fact a temporary. I
expected, but do not know, that in C this would be an object in static
memory. Thus in C++ I'm doing something illegal but in C maybe it's
perfectly fine.

Is this correct?
 
K

Keith Thompson

nroberts said:
I've been playing around with an object library and have run into an
inconsistency between using it under a C compiler and using it under a
C++ compiler.

I wanted a way to declare "objects" statically, meaning they exist as
constants. I did something like the following:

struct Object {
struct Class const* isa;
};

struct String_ {
struct Object const _;
char const* buf;
int len;
};

extern void* __X_STR;

#define xstr(X) &(struct String_){ { __X_STR }, X, sizeof(X) };

The '__X_STR' variable is defined statically in a C file.

Later I can do the following:

void* s = xstr("Hello World!);

This works fine under gcc but pitches a fit under g++ about taking the
address of a temporary.

In C++ the expression (struct String_)... is in fact a temporary. I
expected, but do not know, that in C this would be an object in static
memory. Thus in C++ I'm doing something illegal but in C maybe it's
perfectly fine.

Is this correct?

First of all, avoid creating identifiers that start with an underscore;
most of them are reserved to the implementation. (There's a bit more to
it than that, but "never create identifiers starting with _" is an
easier rule to remember.)

In C,

(struct String_){ ... }

is a compound literal. As C11 6.5.2.5p5 says (C99 is similar, if not
identical):

The value of the compound literal is that of an unnamed object
initialized by the initializer list. If the compound literal
occurs outside the body of a function, the object has static
storage duration; otherwise, it has automatic storage duration
associated with the enclosing block.

I don't think it's referred to as a *temporary*, but there is some
danger of letting a pointer to the object escape the object's scope.

<OT>
C++, even as of the new 2011 ISO standard, does not support compound
literals. They appear to be a g++ extension. You'll have to consult
the gcc documentation to find out how they behave.
</OT>
 
E

Eric Sosman

I've been playing around with an object library and have run into an
inconsistency between using it under a C compiler and using it under a
C++ compiler.

This is about as surprising as if you'd found an inconsistency
when running the same code through a COBOL compiler. C and C++ are
different languages. They are similar in many points, but the only
purpose of those similarities is to entrap the unwary.
I wanted a way to declare "objects" statically, meaning they exist as
constants. I did something like the following:

"Something like." O frabjous day. O diem praeclarum. Whoopee.
struct Object {
struct Class const* isa;
};

struct String_ {
struct Object const _;
char const* buf;
int len;

Aside: `size_t' might be better here.
};

extern void* __X_STR;

Reserved identifier. If the implementation attaches some
unexpected meaning to it (and no, it's not required to document
the fact), that's your tough luck for infringing its name space.
#define xstr(X) &(struct String_){ { __X_STR }, X, sizeof(X) };

You probably don't want the semicolon.
The '__X_STR' variable is defined statically in a C file.

Bad idea, as mentioned above.
Later I can do the following:

void* s = xstr("Hello World!);

Missing a quotation mark.
This works fine under gcc but pitches a fit under g++ about taking the
address of a temporary.

Well, no: "this" does not "work fine under gcc" because gcc
won't even compile it. "Something derivable from this" may be
working for you -- but if I've imagined a different "something"
than what you're actually using, my advice may do you little good.
Again, that's your tough luck.
In C++ the expression (struct String_)... is in fact a temporary. I
expected, but do not know, that in C this would be an object in static
memory. Thus in C++ I'm doing something illegal but in C maybe it's
perfectly fine.

Is this correct?

It depends on where your `xstr' appears. If it's outside a
function the literal has static storage duration; inside, it has
automatic duration and vanishes when the enclosing block exits.
See 6.5.2.5p5.
 
I

Ike Naar

I've been playing around with an object library and have run into an
inconsistency between using it under a C compiler and using it under a
C++ compiler.

I wanted a way to declare "objects" statically, meaning they exist as
constants. I did something like the following:

struct Object {
struct Class const* isa;
};

struct String_ {
struct Object const _;
char const* buf;
int len;
};

extern void* __X_STR;

#define xstr(X) &(struct String_){ { __X_STR }, X, sizeof(X) };

The '__X_STR' variable is defined statically in a C file.

Elsethread is has been explained why __X_STR is not a well chosen name.
What has not been mentioned yet is that name mangling can be a problem.
You say the __X_STR variable is defined in a C file. If you refer to
it as plain extern in a C++ file the names will probably not match, and
you'll have to use

extern "C" void * __X_STR;
 
N

nroberts

First of all, avoid creating identifiers that start with an underscore;
most of them are reserved to the implementation. (There's a bit more to
it than that, but "never create identifiers starting with _" is an
easier rule to remember.)

In C,

    (struct String_){ ... }

is a compound literal. As C11 6.5.2.5p5 says (C99 is similar, if not
identical):

    The value of the compound literal is that of an unnamed object
    initialized by the initializer list. If the compound literal
    occurs outside the body of a function, the object has static
    storage duration; otherwise, it has automatic storage duration
    associated with the enclosing block.

I don't think it's referred to as a *temporary*, but there is some
danger of letting a pointer to the object escape the object's scope.

<OT>
C++, even as of the new 2011 ISO standard, does not support compound
literals. They appear to be a g++ extension. You'll have to consult
the gcc documentation to find out how they behave.
</OT>

Thanks for this. Answers everything I needed to know to move
forward. This helps a great deal and lies in complete contrast to Mr.
Sosman's nastiness, which didn't even answer anything. Your answer is
much appreciated.
 
N

nroberts

I've been playing around with an object library and have run into an
inconsistency between using it under a C compiler and using it under a
C++ compiler.
[snip]

Elsethread is has been explained why __X_STR is not a well chosen name.
What has not been mentioned yet is that name mangling can be a problem.
You say the __X_STR variable is defined in a C file. If you refer to
it as plain extern in a C++ file the names will probably not match, and
you'll have to use

  extern "C" void * __X_STR;

Yeah, I'm doing that. Thanks.

Only reason this turned up is I'm testing the library with Boost.Test
so I'm having to familiarize myself with the many subtle differences
between the languages.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top