Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #23384 > unrolled thread

Taking address of struct temporary

Started bynroberts <roberts.noah@gmail.com>
First post2012-07-18 18:58 -0700
Last post2012-07-19 08:57 -0700
Articles 6 — 4 participants

Back to article view | Back to comp.lang.c


Contents

  Taking address of struct temporary nroberts <roberts.noah@gmail.com> - 2012-07-18 18:58 -0700
    Re: Taking address of struct temporary Keith Thompson <kst-u@mib.org> - 2012-07-18 19:27 -0700
      Re: Taking address of struct temporary nroberts <roberts.noah@gmail.com> - 2012-07-19 08:54 -0700
    Re: Taking address of struct temporary Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-07-18 22:31 -0400
    Re: Taking address of struct temporary Ike Naar <ike@sverige.freeshell.org> - 2012-07-19 06:31 +0000
      Re: Taking address of struct temporary nroberts <roberts.noah@gmail.com> - 2012-07-19 08:57 -0700

#23384 — Taking address of struct temporary

Fromnroberts <roberts.noah@gmail.com>
Date2012-07-18 18:58 -0700
SubjectTaking address of struct temporary
Message-ID<73b21861-a104-4d94-8d44-747adbfbb7b3@t1g2000pbl.googlegroups.com>
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?

[toc] | [next] | [standalone]


#23385

FromKeith Thompson <kst-u@mib.org>
Date2012-07-18 19:27 -0700
Message-ID<lnk3y0bi3h.fsf@nuthaus.mib.org>
In reply to#23384
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"

[toc] | [prev] | [next] | [standalone]


#23398

Fromnroberts <roberts.noah@gmail.com>
Date2012-07-19 08:54 -0700
Message-ID<5a027e58-ee71-478e-8bb2-2e99b6b30e8c@h20g2000yqe.googlegroups.com>
In reply to#23385
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.

[toc] | [prev] | [next] | [standalone]


#23386

FromEric Sosman <esosman@ieee-dot-org.invalid>
Date2012-07-18 22:31 -0400
Message-ID<ju7rie$83q$1@dont-email.me>
In reply to#23384
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

[toc] | [prev] | [next] | [standalone]


#23388

FromIke Naar <ike@sverige.freeshell.org>
Date2012-07-19 06:31 +0000
Message-ID<slrn3vfsk0faev.ke4.ike@sverige.freeshell.org>
In reply to#23384
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;

[toc] | [prev] | [next] | [standalone]


#23399

Fromnroberts <roberts.noah@gmail.com>
Date2012-07-19 08:57 -0700
Message-ID<7f81781a-cb12-4c99-a404-054181f98d01@d32g2000yqn.googlegroups.com>
In reply to#23388
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.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web