Taking address of struct temporary

Discussion in 'C Programming' started by nroberts, Jul 19, 2012.

  1. nroberts

    nroberts Guest

    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?
     
    nroberts, Jul 19, 2012
    #1
    1. Advertising

  2. nroberts <> 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) <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"
     
    Keith Thompson, Jul 19, 2012
    #2
    1. Advertising

  3. nroberts

    Eric Sosman Guest

    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
    d
     
    Eric Sosman, Jul 19, 2012
    #3
  4. nroberts

    Ike Naar Guest

    On 2012-07-19, 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.
    >
    > 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;
     
    Ike Naar, Jul 19, 2012
    #4
  5. nroberts

    nroberts Guest

    On Jul 18, 7:27 pm, Keith Thompson <> wrote:
    > nroberts <> 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, Jul 19, 2012
    #5
  6. nroberts

    nroberts Guest

    On Jul 18, 11:31 pm, Ike Naar <> wrote:
    > On 2012-07-19, 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.

    >

    [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.
     
    nroberts, Jul 19, 2012
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Henning Hasemann
    Replies:
    17
    Views:
    1,170
    mangesh
    Jun 30, 2006
  2. Replies:
    0
    Views:
    1,129
  3. Replies:
    3
    Views:
    748
  4. Replies:
    7
    Views:
    3,261
    James Kanze
    Feb 12, 2008
  5. Andy Gibbs
    Replies:
    5
    Views:
    4,082
    Andy Gibbs
    Nov 19, 2008
Loading...

Share This Page