Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Taking address of struct temporary (http://www.velocityreviews.com/forums/t948252-taking-address-of-struct-temporary.html)

nroberts 07-19-2012 01:58 AM

Taking address of struct temporary
 
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?

Keith Thompson 07-19-2012 02:27 AM

Re: Taking address of struct temporary
 
nroberts <roberts.noah@gmail.com> writes:
> 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>

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Eric Sosman 07-19-2012 02:31 AM

Re: Taking address of struct temporary
 
On 7/18/2012 9:58 PM, nroberts wrote:
> 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.

--
Eric Sosman
esosman@ieee-dot-org.invalid

Ike Naar 07-19-2012 06:31 AM

Re: Taking address of struct temporary
 
On 2012-07-19, nroberts <roberts.noah@gmail.com> wrote:
> 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;

nroberts 07-19-2012 03:54 PM

Re: Taking address of struct temporary
 
On Jul 18, 7:27*pm, Keith Thompson <ks...@mib.org> wrote:
> nroberts <roberts.n...@gmail.com> writes:
> > 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>


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.

nroberts 07-19-2012 03:57 PM

Re: Taking address of struct temporary
 
On Jul 18, 11:31*pm, Ike Naar <i...@sverige.freeshell.org> wrote:
> On 2012-07-19, nroberts <roberts.n...@gmail.com> wrote:
>


> > 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.


All times are GMT. The time now is 06:11 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.