Initializing compound type containing opaque type

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Nate Eldredge

    #1

    Initializing compound type containing opaque type

    Consider the following pseudo-code:

    #include <opaque.h>

    struct foo {
    int a;
    opaque_t op;
    int b;
    };

    struct foo blah = { 17, /* ??? */ , 23 };

    Here we suppose that `opaque_t' is defined in <opaque.has some type
    not known to us, or which we cannot rely on. In particular, it may be
    a scalar or compound type. The goal is to initialize `blah' in such a
    way that `blah.a == 17' and `blah.b == 23'. We don't care about the
    value of `blah.op'.

    It seems to me that there is no way to do this in standard C. Is this
    correct, or am I missing something?

    A workaround would be to rearrange the members of `struct foo' as

    struct foo2 {
    int a;
    int b;
    opaque_t op;
    };

    struct foo2 blah2 = { 17, 23 };

    I believe this is legal, but I could be wrong. My compiler warns
    about a missing initializer, but accepts the code.

    If `opaque_t' is known to be a compound type, we could write

    struct foo blah3 = { 17, { }, 23 };

    which again provokes a missing initializer warning but is accepted.
    Again I am curious whether it is actually legal.

    I thought of this issue after reading a post here a couple weeks ago,
    "Exception handling crashes or exits" by Fabiano Sidler,
    <48c4e24d$1_4@n ews.bluewin.ch> , in which the poster wants a struct
    with a jmp_buf as one member. He initializes that member with { 0 },
    which is certainly non-portable. But I wondered if there is a
    portable way to do the same thing.

    If not, it seems like it might be useful for the authors of <opaque.h>
    to provide a macro which is suitable as an initializer for opaque_t.
    E.g. <opaque.hmigh t contain

    typedef opaque_t struct {
    int x,
    double d;
    };

    #define OPAQUE_INITIALI ZER { 0, 0.0 }

    so that one could write

    struct foo blah = { 17, OPAQUE_INITIALI ZER, 23 };

    In particular, this could be a useful extension for library authors to
    provide for opaque library types (e.g. jmp_buf, FILE, etc).

    Any thoughts?
  • vippstar@gmail.com

    #2
    Re: Initializing compound type containing opaque type

    On Oct 2, 12:05 am, Nate Eldredge <n...@vulcan.la nwrote:
    Consider the following pseudo-code:
    >
    #include <opaque.h>
    >
    struct foo {
    int a;
    opaque_t op;
    int b;
    >
    };
    >
    struct foo blah = { 17, /* ??? */ , 23 };
    >
    Here we suppose that `opaque_t' is defined in <opaque.has some type
    not known to us, or which we cannot rely on. In particular, it may be
    a scalar or compound type. The goal is to initialize `blah' in such a
    way that `blah.a == 17' and `blah.b == 23'. We don't care about the
    value of `blah.op'.
    >
    It seems to me that there is no way to do this in standard C. Is this
    correct, or am I missing something?
    >
    A workaround would be to rearrange the members of `struct foo' as
    >
    struct foo2 {
    int a;
    int b;
    opaque_t op;
    >
    };
    >
    struct foo2 blah2 = { 17, 23 };
    >
    I believe this is legal, but I could be wrong. My compiler warns
    about a missing initializer, but accepts the code.
    Yes, it's legal.
    (note: In POSIX it wouldn't be; *_t are reserved identifiers)
    If `opaque_t' is known to be a compound type, we could write
    >
    struct foo blah3 = { 17, { }, 23 };
    >
    which again provokes a missing initializer warning but is accepted.
    Again I am curious whether it is actually legal.
    Also legal.
    I thought of this issue after reading a post here a couple weeks ago,
    "Exception handling crashes or exits" by Fabiano Sidler,
    <48c4e24d$...@n ews.bluewin.ch> , in which the poster wants a struct
    with a jmp_buf as one member. He initializes that member with { 0 },
    which is certainly non-portable. But I wondered if there is a
    portable way to do the same thing.
    Yes, jmp_buf foo = {0};

    Though that'd initialize all members to 0, 0.0 or NULL depending on
    type, recursively applied for any aggregate
    If not, it seems like it might be useful for the authors of <opaque.h>
    to provide a macro which is suitable as an initializer for opaque_t.
    Well, it is legal, so it's not useful.
    E.g. <opaque.hmigh t contain
    <snip>

    Comment

    • Eric Sosman

      #3
      Re: Initializing compound type containing opaque type

      Nate Eldredge wrote:
      Consider the following pseudo-code:
      >
      #include <opaque.h>
      >
      struct foo {
      int a;
      opaque_t op;
      int b;
      };
      >
      struct foo blah = { 17, /* ??? */ , 23 };
      >
      Here we suppose that `opaque_t' is defined in <opaque.has some type
      not known to us, or which we cannot rely on. In particular, it may be
      a scalar or compound type. The goal is to initialize `blah' in such a
      way that `blah.a == 17' and `blah.b == 23'. We don't care about the
      value of `blah.op'.
      In C99 you could use a "compound literal:"

      struct foo blah = (struct foo){.a = 17, .b = 23};

      (Double-check my syntax; I'm typing this hurriedly.)

      In C90 you could initialize the unknown member to "zero of
      the appropriate type:"

      struct foo blah = { 17, { 0 }, 23 };

      Some compilers may emit warnings for too few initializers, but
      the initialization is valid; if opaque_t is compound, its sub-
      elements are initialized to appropriate zeroes. The warnings may
      be a nuisance, but they do no actual harm.

      --
      Eric.Sosman@sun .com

      Comment

      • Barry Schwarz

        #4
        Re: Initializing compound type containing opaque type

        On Wed, 01 Oct 2008 14:05:53 -0700, Nate Eldredge <nate@vulcan.la n>
        wrote:
        >Consider the following pseudo-code:
        >
        >#include <opaque.h>
        >
        >struct foo {
        int a;
        opaque_t op;
        int b;
        >};
        >
        >struct foo blah = { 17, /* ??? */ , 23 };
        >
        >Here we suppose that `opaque_t' is defined in <opaque.has some type
        >not known to us, or which we cannot rely on. In particular, it may be
        >a scalar or compound type. The goal is to initialize `blah' in such a
        >way that `blah.a == 17' and `blah.b == 23'. We don't care about the
        >value of `blah.op'.
        >
        >It seems to me that there is no way to do this in standard C. Is this
        >correct, or am I missing something?
        >
        >A workaround would be to rearrange the members of `struct foo' as
        >
        >struct foo2 {
        int a;
        int b;
        opaque_t op;
        >};
        >
        >struct foo2 blah2 = { 17, 23 };
        >
        >I believe this is legal, but I could be wrong. My compiler warns
        >about a missing initializer, but accepts the code.
        An insufficient quantity of initializers is specifically allowed
        (6.7.8-19 and -21). Compilers are allowed to issue diagnostic
        messages for correct code. Some do so when assigning an int to a char
        or when using gets. These are not so much warnings (a term not
        defined in the standard) but more like reminders to the programmer
        that something is "unusual" and worth a second look. As long as the
        code complies with the standard, the compiler is obligated to accept
        it.
        >
        >If `opaque_t' is known to be a compound type, we could write
        >
        >struct foo blah3 = { 17, { }, 23 };
        >
        >which again provokes a missing initializer warning but is accepted.
        >Again I am curious whether it is actually legal.
        >
        >I thought of this issue after reading a post here a couple weeks ago,
        >"Exception handling crashes or exits" by Fabiano Sidler,
        ><48c4e24d$1_4@ news.bluewin.ch >, in which the poster wants a struct
        >with a jmp_buf as one member. He initializes that member with { 0 },
        >which is certainly non-portable. But I wondered if there is a
        It is portable, for both aggregate and scalar objects. See 6.7.8-16,
        -11, and -19.
        >portable way to do the same thing.
        >
        >If not, it seems like it might be useful for the authors of <opaque.h>
        >to provide a macro which is suitable as an initializer for opaque_t.
        >E.g. <opaque.hmigh t contain
        >
        >typedef opaque_t struct {
        int x,
        double d;
        >};
        >
        >#define OPAQUE_INITIALI ZER { 0, 0.0 }
        >
        >so that one could write
        >
        >struct foo blah = { 17, OPAQUE_INITIALI ZER, 23 };
        >
        >In particular, this could be a useful extension for library authors to
        >provide for opaque library types (e.g. jmp_buf, FILE, etc).
        {0} should suffice. If the object requires non-zero initialization,
        the library should provide an initialization function.

        --
        Remove del for email

        Comment

        • Nate Eldredge

          #5
          Re: Initializing compound type containing opaque type

          Eric Sosman <Eric.Sosman@su n.comwrites:
          Nate Eldredge wrote:
          >Consider the following pseudo-code:
          >>
          >#include <opaque.h>
          >>
          >struct foo {
          > int a;
          > opaque_t op;
          > int b;
          >};
          >>
          >struct foo blah = { 17, /* ??? */ , 23 };
          >>
          >Here we suppose that `opaque_t' is defined in <opaque.has some type
          >not known to us, or which we cannot rely on. In particular, it may be
          >a scalar or compound type. The goal is to initialize `blah' in such a
          >way that `blah.a == 17' and `blah.b == 23'. We don't care about the
          >value of `blah.op'.
          >
          In C99 you could use a "compound literal:"
          >
          struct foo blah = (struct foo){.a = 17, .b = 23};
          >
          (Double-check my syntax; I'm typing this hurriedly.)
          My compiler says "error: initializer element is not constant". It
          does work if it is moved inside a function, so that blah is auto, but
          that's of course entirely different. (Anyway, in that case we could
          just initialize blah.a and blah.b by hand.)
          In C90 you could initialize the unknown member to "zero of
          the appropriate type:"
          >
          struct foo blah = { 17, { 0 }, 23 };
          >
          Some compilers may emit warnings for too few initializers, but
          the initialization is valid; if opaque_t is compound, its sub-
          elements are initialized to appropriate zeroes. The warnings may
          be a nuisance, but they do no actual harm.
          Interesting, so the OP was correct after all. I never knew about
          "zero of the appropriate type". I assumed that would be wrong if
          opaque_t turned out to be a scalar type, or a compound whose first
          member was also compound, but apparently not. Those clever language
          designers, always one step ahead. :)

          Thanks to all who replied.

          Comment

          • vippstar@gmail.com

            #6
            Re: Initializing compound type containing opaque type

            On Oct 2, 12:05 am, Nate Eldredge <n...@vulcan.la nwrote:
            Consider the following pseudo-code:
            >
            #include <opaque.h>
            >
            struct foo {
            int a;
            opaque_t op;
            int b;
            >
            };
            >
            struct foo blah = { 17, /* ??? */ , 23 };
            >
            Here we suppose that `opaque_t' is defined in <opaque.has some type
            not known to us, or which we cannot rely on. In particular, it may be
            a scalar or compound type. The goal is to initialize `blah' in such a
            way that `blah.a == 17' and `blah.b == 23'. We don't care about the
            value of `blah.op'.
            >
            It seems to me that there is no way to do this in standard C. Is this
            correct, or am I missing something?
            Whoops, I forgot to reply to this question at my post.
            In C99 you can.

            struct foo blah = { .a = 17, .b = 23 };

            Mr Sossman mentioned compound literals, but I'm unsure why he didn't
            mention this which is even simpler.

            You can also do this for array elements

            char foo[2] = { .[1] = 'a' };

            Comment

            • vippstar@gmail.com

              #7
              Re: Initializing compound type containing opaque type

              On Oct 2, 1:28 am, Eric Sosman <Eric.Sos...@su n.comwrote:
              ....
              In C99 you could use a "compound literal:"
              >
              struct foo blah = (struct foo){.a = 17, .b = 23};
              >
              (Double-check my syntax; I'm typing this hurriedly.)
              I think you mean

              struct foo blah = *(struct foo[]){ { .a = 17, .b = 23 } };

              Comment

              • Ben Bacarisse

                #8
                Re: Initializing compound type containing opaque type

                Nate Eldredge <nate@vulcan.la nwrites:
                Eric Sosman <Eric.Sosman@su n.comwrites:
                >
                >Nate Eldredge wrote:
                >>Consider the following pseudo-code:
                >>>
                >>#include <opaque.h>
                >>>
                >>struct foo {
                >> int a;
                >> opaque_t op;
                >> int b;
                >>};
                >>>
                >>struct foo blah = { 17, /* ??? */ , 23 };
                >>>
                >>Here we suppose that `opaque_t' is defined in <opaque.has some type
                >>not known to us, or which we cannot rely on. In particular, it may be
                >>a scalar or compound type. The goal is to initialize `blah' in such a
                >>way that `blah.a == 17' and `blah.b == 23'. We don't care about the
                >>value of `blah.op'.
                >>
                > In C99 you could use a "compound literal:"
                >>
                > struct foo blah = (struct foo){.a = 17, .b = 23};
                >>
                >(Double-check my syntax; I'm typing this hurriedly.)
                Not allowed, I think, at file scope.
                My compiler says "error: initializer element is not constant".
                Just use the "initialise r list" rather than providing a compound
                literal. I.e. write:

                struct foo blah = {.a = 17, .b = 23};

                This works for file-scope declarations as well as block-scope ones.
                It
                does work if it is moved inside a function, so that blah is auto, but
                that's of course entirely different.
                Yes. 6.7.8 paragraph 13 permits an expression of "compatible
                structure or union type" when the object has automatic storage. You
                have to read though to paragraph 16 to get to the text:

                "Otherwise, the initializer for an object that has aggregate or
                union type shall be a brace-enclosed list of initializers... "

                to see that a compound literal is not allowed as the sole "top-level"
                initialiser for an object with static storage duration. At least that
                is my explanation of your error message.

                --
                Ben.

                Comment

                • Ben Bacarisse

                  #9
                  Re: Initializing compound type containing opaque type

                  vippstar@gmail. com writes:
                  <snip>
                  You can also do this for array elements
                  >
                  char foo[2] = { .[1] = 'a' };
                  There's no dot. I.e.:

                  char foo[2] = { [1] = 'a' };

                  --
                  Ben.

                  Comment

                  • Eric Sosman

                    #10
                    Re: Initializing compound type containing opaque type

                    vippstar@gmail. com wrote:
                    [...]
                    Whoops, I forgot to reply to this question at my post.
                    In C99 you can.
                    >
                    struct foo blah = { .a = 17, .b = 23 };
                    >
                    Mr Sossman mentioned compound literals, but I'm unsure why he didn't
                    mention this which is even simpler.
                    Because I was (as I said) in a hurry, typing faster than
                    I was thinking. An insalubrious habit ...

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

                    Comment

                    • William Pursell

                      #11
                      Re: Initializing compound type containing opaque type

                      On 1 Oct, 22:05, Nate Eldredge <n...@vulcan.la nwrote:
                      Consider the following pseudo-code:
                      >
                      #include <opaque.h>
                      >
                      struct foo {
                             int a;
                             opaque_t op;
                             int b;
                      >
                      };
                      >
                      If opaque_t is truly opaque, and not specified
                      in opaque.h, then the compiler won't accept
                      this definition of struct foo. If the compiler
                      is accepting this, then the header is specifying
                      opaque_t completely, so (I would argue) has
                      misnamed it because it isn't opaque.
                      struct foo blah = { 17, /* ??? */ , 23 };
                      >
                      Here we suppose that `opaque_t' is defined in <opaque.has some type
                      not known to us, or which we cannot rely on.
                      I don't understand what you mean by "not known to us". If
                      the compiler can get the definition from opaque_t, then
                      you can, too! Am I using the word "opaque" in a
                      stricter sense than you? When I say opaque type,
                      I mean that the header contains no more than:
                      typedef struct opaque * opaque_t;
                      or just:
                      struct opaque;

                      <snip>
                      If not, it seems like it might be useful for the authors of <opaque.h>
                      to provide a macro which is suitable as an initializer for opaque_t.
                      E.g. <opaque.hmigh t contain
                      >
                      typedef opaque_t struct {
                              int x,
                              double d;
                      >
                      };
                      Is this an opaque type? It's got an int and
                      a double, so ... no, it's not. At least not
                      by my understanding of the word opaque.

                      Comment

                      • William Pursell

                        #12
                        Re: Initializing compound type containing opaque type

                        On 2 Oct, 00:45, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
                        vipps...@gmail. com writes:
                        >
                        <snip>
                        >
                        You can also do this for array elements
                        >
                        char foo[2] = { .[1] = 'a' };
                        >
                        There's no dot.  I.e.:
                        >
                          char foo[2] = { [1] = 'a' };
                        Is that C99? I thought that was a gnu extension.

                        Comment

                        • Nate Eldredge

                          #13
                          Re: Initializing compound type containing opaque type

                          William Pursell <bill.pursell@g mail.comwrites:
                          On 1 Oct, 22:05, Nate Eldredge <n...@vulcan.la nwrote:
                          >Consider the following pseudo-code:
                          >>
                          >#include <opaque.h>
                          >>
                          >struct foo {
                          >       int a;
                          >       opaque_t op;
                          >       int b;
                          >>
                          >};
                          >>
                          >
                          If opaque_t is truly opaque, and not specified
                          in opaque.h, then the compiler won't accept
                          this definition of struct foo. If the compiler
                          is accepting this, then the header is specifying
                          opaque_t completely, so (I would argue) has
                          misnamed it because it isn't opaque.
                          By "opaque" I mean an object whose format and contents are not
                          intended to be used by the programmer, and are subject to change.
                          This is how I've heard it used in the past.

                          jmp_buf is an example. Certainly you can open up <setjmp.hand find
                          out how it is defined on your system; maybe it's a struct with a
                          member for each of your CPU's registers. But you can't use any of
                          that information in a portable program, since on another system, or a
                          later version of the same system, it may be defined differently, or
                          used differently by the library, so in a more general sense you don't
                          really "know" how it's defined. All you "know" about jmp_buf is that
                          you can create one using setjmp() and pass it to longjmp() later on.
                          From the programmer's point of view it's just a magic cookie.

                          Other examples in the standard library would be time_t and FILE.
                          div_t is a library type that I would not call opaque; it is documented
                          as being a struct with two members, `quot' and `rem', whose types and
                          meanings are well described and guaranteed to be the same in all
                          conforming implementations .

                          Comment

                          • Ben Bacarisse

                            #14
                            Re: Initializing compound type containing opaque type

                            William Pursell <bill.pursell@g mail.comwrites:
                            On 2 Oct, 00:45, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
                            >vipps...@gmail .com writes:
                            >>
                            ><snip>
                            >>
                            You can also do this for array elements
                            >>
                            char foo[2] = { .[1] = 'a' };
                            >>
                            >There's no dot.  I.e.:
                            >>
                            >  char foo[2] = { [1] = 'a' };
                            >
                            Is that C99? I thought that was a gnu extension.
                            Yes, it is C99:

                            designation:
                            designator-list =

                            designator-list:
                            designator
                            designator-list designator

                            designator:
                            [ constant-expression ]
                            . identifier

                            --
                            Ben.

                            Comment

                            • James Kuyper

                              #15
                              Re: Initializing compound type containing opaque type

                              William Pursell wrote:
                              On 2 Oct, 00:45, Ben Bacarisse <ben.use...@bsb .me.ukwrote:
                              ....
                              > char foo[2] = { [1] = 'a' };
                              >
                              Is that C99? ...
                              Yes.

                              Comment

                              Working...