How come C allow structure members to be addressed like an array ?

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

    How come C allow structure members to be addressed like an array ?

    #include <stdio.h>

    typedef struct
    {
    double x, y, z;
    }vector;

    int main(void)
    {
    int i;
    vector v;
    double *cord;

    v.x = 10;
    v.y = 1;
    v.z = 2;

    cord = &v.x;

    for(i = 0; i < 3; i++)
    {
    printf("%f\n", cord[i]);
    }
    return 0;
    }

    here's the output i get:
    10.000000
    1.000000
    2.000000

    which is the same as v

    i don't how it happens as i was just trying some random ideas but
    great stuff really. helped me to reduce some of my code to almost
    1/3rd its size.
  • EventHelix.com

    #2
    Re: How come C allow structure members to be addressed like an array?

    On Jun 14, 5:37 pm, pereges <Brol...@gmail. comwrote:
    #include <stdio.h>
    >
    typedef struct
    {
      double x, y, z;
    >
    }vector;
    >
    int main(void)
    {
      int i;
      vector v;
      double *cord;
    >
      v.x = 10;
      v.y = 1;
      v.z = 2;
    >
     cord = &v.x;
    >
     for(i = 0; i < 3; i++)
     {
      printf("%f\n", cord[i]);
     }
    return 0;
    >
    }
    >
    here's the output i get:
    10.000000
    1.000000
    2.000000
    >
    which is the same as v
    >
    i don't how it happens as i was just trying some random ideas but
    great stuff really. helped me to reduce some of my code to almost
    1/3rd its size.
    This is not portable but at the low level there is no difference
    between a structure containing three doubles and an array of three
    doubles in this case.

    You cannot assume this, as some implementation might introduce pads
    for byte alignment in structures.

    The following articles should help:





    --
    EventStudio 4.0 - http://www.Eventhelix.com/Eventstudio/
    Sequence diagram based systems engineering tool

    Comment

    • Richard Tobin

      #3
      Re: How come C allow structure members to be addressed like an array?

      In article <a0e2a186-8474-4c1f-8649-d713977977ec@34 g2000hsf.google groups.com>,
      EventHelix.com <eventhelix@gma il.comwrote:
      >This is not portable but at the low level there is no difference
      >between a structure containing three doubles and an array of three
      >doubles in this case.
      Fields in a struct are aligned in "an implementation-defined manner
      appropriate to [their] type". The clear implication is that the
      padding is a property of the type (rather than each individual
      instance) and so it would be unreasonable for the padding of
      successive members of the same type in a struct to be different from
      that in an array - which is to say, there should be no padding between
      fields of the same type.

      Can anyone come up with a reason (other than perverseness) why an
      implementation would not do this?

      -- Richard
      --
      In the selection of the two characters immediately succeeding the numeral 9,
      consideration shall be given to their replacement by the graphics 10 and 11 to
      facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)

      Comment

      • pereges

        #4
        Re: How come C allow structure members to be addressed like an array?

        one can solve this problem using a vector iterator function like below
        but i am not sure if the solution is generic :

        #include <stdio.h>

        typedef struct
        {
        double x, y, z;

        }vector;

        double vector_iterator (vector *a, int i)
        {
        double ret;
        if(i == 0)
        ret = a->x;
        if(i == 1)
        ret = a->y;
        if(i == 2)
        ret = a->z;
        return ret;
        }

        int main(void)
        {
        int i;
        vector v;
        double coord;

        v.x = 10;
        v.y = 1;
        v.z = 2;

        for(i = 0; i < 3; i++)
        {
        coord = vector_iterator (&v, i);
        printf("%f\n", coord);
        }
        return 0;

        }

        Comment

        • =?ISO-8859-1?Q?Tom=E1s_=D3_h=C9ilidhe?=

          #5
          Re: How come C allow structure members to be addressed like an array?


          Others have explained the padding situation, but if you want re-
          assurance, you might add a routine to the start of your code that
          makes sure it's OK:

          void EnsureItWorks(v oid)
          {
          Vector const v = { 99, 56, 42 };

          if (99 == (&v.x)[0] &&
          56 == (&v.x)[1] &&
          42 == (&v.x)[2]) return;

          puts("ERROR: There's padding in the Vector struct.");

          exit(EXIT_FAILU RE);
          }

          int main(void) { EnsureItWorks() ; }


          (I know that floating-point arithmetic isn't exact but as far as I
          know it's exact for integer values... but I'm open to correction!)

          Comment

          • badc0de4@gmail.com

            #6
            Re: How come C allow structure members to be addressed like an array?

            Tomás Ó hÉilidhe wrote:
            void EnsureItWorks(v oid)
            {
            Vector const v = { 99, 56, 42 };
            >
            if (99 == (&v.x)[0] &&
            56 == (&v.x)[1] &&
            42 == (&v.x)[2]) return;
            *BANG*
            (&v.x)[1] or (&v.x)[2] is a trap representation :)
            puts("ERROR: There's padding in the Vector struct.");
            >
            exit(EXIT_FAILU RE);
            }

            Comment

            • Ian Collins

              #7
              Re: How come C allow structure members to be addressed like an array?

              Tomás Ó hÉilidhe wrote:
              Others have explained the padding situation, but if you want re-
              assurance, you might add a routine to the start of your code that
              makes sure it's OK:
              >
              void EnsureItWorks(v oid)
              {
              Vector const v = { 99, 56, 42 };
              >
              if (99 == (&v.x)[0] &&
              56 == (&v.x)[1] &&
              42 == (&v.x)[2]) return;
              >
              puts("ERROR: There's padding in the Vector struct.");
              >
              exit(EXIT_FAILU RE);
              }
              >
              int main(void) { EnsureItWorks() ; }
              >
              A very verbose way of writing

              int main()
              {
              assert( sizeof(vector)= =sizeof(double) *3);
              }

              --
              Ian Collins.

              Comment

              • viza

                #8
                Re: How come C allow structure members to be addressed like anarray ?

                Hi

                On Sun, 15 Jun 2008 10:51:28 +1200, Ian Collins wrote:
                Tomás Ó hÉilidhe wrote:
                > if (99 == (&v.x)[0] &&
                > 56 == (&v.x)[1] &&
                > 42 == (&v.x)[2]) return;
                > puts("ERROR: There's padding in the Vector struct.");
                > exit(EXIT_FAILU RE);
                A very verbose way of writing
                assert( sizeof(vector)= =sizeof(double) *3);
                The two are not equivalent and neither is perfect. Better is:

                assert( offsetof(vector ,y) == sizeof(double)
                && offsetof(vector ,z) == sizeof(double)* 2 );

                viza

                Comment

                • Ian Collins

                  #9
                  Re: How come C allow structure members to be addressed like anarray ?

                  viza wrote:
                  Hi
                  >
                  On Sun, 15 Jun 2008 10:51:28 +1200, Ian Collins wrote:
                  >Tomás Ó hÉilidhe wrote:
                  >
                  >> if (99 == (&v.x)[0] &&
                  >> 56 == (&v.x)[1] &&
                  >> 42 == (&v.x)[2]) return;
                  >> puts("ERROR: There's padding in the Vector struct.");
                  >> exit(EXIT_FAILU RE);
                  >
                  >A very verbose way of writing
                  > assert( sizeof(vector)= =sizeof(double) *3);
                  >
                  The two are not equivalent and neither is perfect. Better is:
                  >
                  assert( offsetof(vector ,y) == sizeof(double)
                  && offsetof(vector ,z) == sizeof(double)* 2 );
                  >
                  Why?

                  Anyway, if offsetof(vector ,z) == sizeof(double)* 2, how can
                  offsetof(vector ,y) be anything other than sizeof(double)?

                  --
                  Ian Collins.

                  Comment

                  • Ben Bacarisse

                    #10
                    Re: How come C allow structure members to be addressed like an array ?

                    Ian Collins <ian-news@hotmail.co mwrites:
                    Tomás Ó hÉilidhe wrote:
                    >Others have explained the padding situation, but if you want re-
                    >assurance, you might add a routine to the start of your code that
                    >makes sure it's OK:
                    >>
                    >void EnsureItWorks(v oid)
                    >{
                    > Vector const v = { 99, 56, 42 };
                    >>
                    > if (99 == (&v.x)[0] &&
                    > 56 == (&v.x)[1] &&
                    > 42 == (&v.x)[2]) return;
                    (&v.x)[0] is guaranteed to be correct. The other two can be better
                    tested just by ensuring that

                    &v.x + 2 == &v.z

                    The value test could give a false positive if the padding between
                    elements happened to have the "right" value.
                    > puts("ERROR: There's padding in the Vector struct.");
                    > exit(EXIT_FAILU RE);
                    >}
                    >>
                    >int main(void) { EnsureItWorks() ; }
                    >>
                    A very verbose way of writing
                    >
                    int main()
                    {
                    assert( sizeof(vector)= =sizeof(double) *3);
                    }
                    Except the structure can have padding at the end and still be suitable.

                    --
                    Ben.

                    Comment

                    • Ben Bacarisse

                      #11
                      Re: How come C allow structure members to be addressed like an array ?

                      Ian Collins <ian-news@hotmail.co mwrites:
                      viza wrote:
                      >Hi
                      >>
                      >On Sun, 15 Jun 2008 10:51:28 +1200, Ian Collins wrote:
                      >>Tomás Ó hÉilidhe wrote:
                      >>
                      >>> if (99 == (&v.x)[0] &&
                      >>> 56 == (&v.x)[1] &&
                      >>> 42 == (&v.x)[2]) return;
                      >>> puts("ERROR: There's padding in the Vector struct.");
                      >>> exit(EXIT_FAILU RE);
                      >>
                      >>A very verbose way of writing
                      >> assert( sizeof(vector)= =sizeof(double) *3);
                      >>
                      >The two are not equivalent and neither is perfect. Better is:
                      >>
                      >assert( offsetof(vector ,y) == sizeof(double)
                      > && offsetof(vector ,z) == sizeof(double)* 2 );
                      >>
                      Why?
                      Tomás's code is over complex (one test is enough) and could fail in
                      unusual cases (see my other posting) and your test will be thrown if
                      there is padding at the end of the struct.
                      Anyway, if offsetof(vector ,z) == sizeof(double)* 2, how can
                      offsetof(vector ,y) be anything other than sizeof(double)?
                      Agreed. I still prefer my address test, though.

                      By the way, This is all about making the best of a bad job. To the
                      OP: if you want to index things, make them an array as Keith Thompson
                      suggested. In addition to using #define to name the elements one
                      could also do:

                      typedef struct {
                      double v[3];
                      } vector;

                      enum { x, y, z };

                      vector point;

                      so that one can write point.v[x] and so on (even x[&point] if you
                      want to make your readers do a double-take!).

                      --
                      Ben.

                      Comment

                      • Ian Collins

                        #12
                        Re: How come C allow structure members to be addressed like anarray ?

                        Ben Bacarisse wrote:
                        Ian Collins <ian-news@hotmail.co mwrites:
                        >
                        >viza wrote:
                        >>Hi
                        >>>
                        >>On Sun, 15 Jun 2008 10:51:28 +1200, Ian Collins wrote:
                        >>>Tomás Ó hÉilidhe wrote:
                        >>>> if (99 == (&v.x)[0] &&
                        >>>> 56 == (&v.x)[1] &&
                        >>>> 42 == (&v.x)[2]) return;
                        >>>> puts("ERROR: There's padding in the Vector struct.");
                        >>>> exit(EXIT_FAILU RE);
                        >>>A very verbose way of writing
                        >>> assert( sizeof(vector)= =sizeof(double) *3);
                        >>The two are not equivalent and neither is perfect. Better is:
                        >>>
                        >>assert( offsetof(vector ,y) == sizeof(double)
                        >> && offsetof(vector ,z) == sizeof(double)* 2 );
                        >>>
                        >Why?
                        >
                        Tomás's code is over complex (one test is enough) and could fail in
                        unusual cases (see my other posting) and your test will be thrown if
                        there is padding at the end of the struct.
                        >
                        OK, make it

                        assert( sizeof(vector[2])==sizeof(doubl e)*6 );

                        Or even a compile time assert:

                        const int n = 1/( sizeof(vector[2])==sizeof(doubl e)*6 );
                        >Anyway, if offsetof(vector ,z) == sizeof(double)* 2, how can
                        >offsetof(vecto r,y) be anything other than sizeof(double)?
                        >
                        Agreed. I still prefer my address test, though.
                        >
                        Fair enough, but the simplified offsetof (or sizeof) test has the
                        (small) advantage of not requiring an instance of vector to test.
                        Saying that, the address test could be evaluated at compile time, so the
                        vector would be eliminated by an optimiser.

                        --
                        Ian Collins.

                        Comment

                        • Keith Thompson

                          #13
                          Re: How come C allow structure members to be addressed like an array ?

                          Ian Collins <ian-news@hotmail.co mwrites:
                          Ben Bacarisse wrote:
                          >Ian Collins <ian-news@hotmail.co mwrites:
                          >>
                          >>viza wrote:
                          >>>Hi
                          >>>>
                          >>>On Sun, 15 Jun 2008 10:51:28 +1200, Ian Collins wrote:
                          >>>>Tomás Ó hÉilidhe wrote:
                          >>>>> if (99 == (&v.x)[0] &&
                          >>>>> 56 == (&v.x)[1] &&
                          >>>>> 42 == (&v.x)[2]) return;
                          >>>>> puts("ERROR: There's padding in the Vector struct.");
                          >>>>> exit(EXIT_FAILU RE);
                          >>>>A very verbose way of writing
                          >>>> assert( sizeof(vector)= =sizeof(double) *3);
                          >>>The two are not equivalent and neither is perfect. Better is:
                          >>>>
                          >>>assert( offsetof(vector ,y) == sizeof(double)
                          >>> && offsetof(vector ,z) == sizeof(double)* 2 );
                          >>>>
                          >>Why?
                          >>
                          >Tomás's code is over complex (one test is enough) and could fail in
                          >unusual cases (see my other posting) and your test will be thrown if
                          >there is padding at the end of the struct.
                          >>
                          OK, make it
                          >
                          assert( sizeof(vector[2])==sizeof(doubl e)*6 );
                          >
                          Or even a compile time assert:
                          >
                          const int n = 1/( sizeof(vector[2])==sizeof(doubl e)*6 );
                          I think that this:

                          sizeof(vector) == sizeof(double) * 3

                          would suffice. An array of two thingies must have twice the size of a
                          single thingie, for any applicable value of "thingie".

                          [snip]

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

                          Comment

                          • vippstar@gmail.com

                            #14
                            Re: How come C allow structure members to be addressed like an array?

                            On Jun 15, 5:27 am, Keith Thompson <ks...@mib.orgw rote:
                            Ian Collins <ian-n...@hotmail.co mwrites:
                            Ben Bacarisse wrote:
                            Ian Collins <ian-n...@hotmail.co mwrites:
                            >
                            >viza wrote:
                            >>Hi
                            >
                            >>On Sun, 15 Jun 2008 10:51:28 +1200, Ian Collins wrote:
                            >>>Tomás Ó hÉilidhe wrote:
                            >>>> if (99 == (&v.x)[0] &&
                            >>>> 56 == (&v.x)[1] &&
                            >>>> 42 == (&v.x)[2]) return;
                            >>>> puts("ERROR: There's padding in the Vector struct.");
                            >>>> exit(EXIT_FAILU RE);
                            >>>A very verbose way of writing
                            >>> assert( sizeof(vector)= =sizeof(double) *3);
                            >>The two are not equivalent and neither is perfect. Better is:
                            >
                            >>assert( offsetof(vector ,y) == sizeof(double)
                            >> && offsetof(vector ,z) == sizeof(double)* 2 );
                            >
                            >Why?
                            >
                            Tomás's code is over complex (one test is enough) and could fail in
                            unusual cases (see my other posting) and your test will be thrown if
                            there is padding at the end of the struct.
                            >
                            OK, make it
                            >
                            assert( sizeof(vector[2])==sizeof(doubl e)*6 );
                            >
                            Or even a compile time assert:
                            >
                            const int n = 1/( sizeof(vector[2])==sizeof(doubl e)*6 );
                            >
                            I think that this:
                            >
                            sizeof(vector) == sizeof(double) * 3
                            >
                            would suffice. An array of two thingies must have twice the size of a
                            single thingie, for any applicable value of "thingie".
                            vector is not an array, it's a struct.
                            This:
                            struct vector { double x, y, z; };
                            sizeof(struct vector)
                            Needs not to evaluate to sizeof (double) * 3.
                            If it were a vector (array), then yes, it is guaranteed and you are
                            correct.
                            But vector is a struct.

                            Thomas: Please change your name to ASCII.

                            Comment

                            • Ian Collins

                              #15
                              Re: How come C allow structure members to be addressed like anarray ?

                              Keith Thompson wrote:
                              Ian Collins <ian-news@hotmail.co mwrites:
                              >Ben Bacarisse wrote:
                              >>Tomás's code is over complex (one test is enough) and could fail in
                              >>unusual cases (see my other posting) and your test will be thrown if
                              >>there is padding at the end of the struct.
                              >>>
                              >OK, make it
                              >>
                              >assert( sizeof(vector[2])==sizeof(doubl e)*6 );
                              >>
                              >Or even a compile time assert:
                              >>
                              >const int n = 1/( sizeof(vector[2])==sizeof(doubl e)*6 );
                              >
                              I think that this:
                              >
                              sizeof(vector) == sizeof(double) * 3
                              >
                              would suffice. An array of two thingies must have twice the size of a
                              single thingie, for any applicable value of "thingie".
                              >
                              It would, my last suggestion was pointless. It would still fail if
                              there were padding at the end of the struct. I would still use the one
                              above, the chances of padding at the end but not in the middle are slim.

                              --
                              Ian Collins.

                              Comment

                              Working...