struct named 0

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Mohd Hanafiah Abdullah

    #1

    struct named 0


    Is the following code conformat to ANSI C?

    typedef struct {
    int a;
    int b;
    } doomdata;

    int main(void)
    {
    int x;

    x = (int)&((doomdat a*)0)->b;
    printf("x=%d\n" , x);
    return x;
    }

    The part,
    (int)&((doomdat a*)0)->b;

    is it conformant to ANSI C? What is it supposed to do?

    Thanks for any tips.

    Napi

    --


  • Michael Mair

    #2
    Re: struct named 0

    Mohd Hanafiah Abdullah wrote:
    [color=blue]
    > Is the following code conformat to ANSI C?
    >
    > typedef struct {
    > int a;
    > int b;
    > } doomdata;
    >
    > int main(void)
    > {
    > int x;
    >
    > x = (int)&((doomdat a*)0)->b;
    > printf("x=%d\n" , x);
    > return x;
    > }
    >
    > The part,
    > (int)&((doomdat a*)0)->b;
    >
    > is it conformant to ANSI C? What is it supposed to do?[/color]

    According to prior discussions, it is at least shady but
    probably not conformant, depending on whether the address
    0 is dereferenced or not.
    This is a version of the offsetof macro from <stddef.h>:
    offsetof(doomda ta,b)
    gives you the byte offset of b in struct doomsdata, that means
    if we have
    struct doomdata d;
    unsigned char *p = (unsigned char *)&d;
    then the address of d.b is p+offsetof(doom data,b).
    In contrast to offsetof which expands to an expression of
    type size_t, the above will give you an int.

    Use offsetof.


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.

    Comment

    • S.Tobias

      #3
      Re: struct named 0

      Mohd Hanafiah Abdullah <napi@cs.indian a.edu> wrote:
      [color=blue]
      > typedef struct {
      > int a;
      > int b;
      > } doomdata;[/color]
      [color=blue]
      > (int)&((doomdat a*)0)->b;[/color]
      [color=blue]
      > is it conformant to ANSI C?[/color]

      IMO no, because it doesn't point to any valid object, so
      invokes UB.

      Question to others:
      Would this be correct?
      (int)&((doomdat a*)0)->a;

      --
      Stan Tobias
      mailx `echo siXtY@FamOuS.Be dBuG.pAlS.INVALID | sed s/[[:upper:]]//g`

      Comment

      • Malcolm

        #4
        Re: struct named 0


        "Mohd Hanafiah Abdullah" <napi@cs.indian a.edu> wrote[color=blue]
        >
        > The part,
        > (int)&((doomdat a*)0)->b;
        >
        > is it conformant to ANSI C? What is it supposed to do?
        >[/color]
        This is the offsetof() macro, which calculates the offset of a structure
        member relative to the struct origin.
        On most platforms it works, but it suffers a few problems on unusual
        systems. For instance, if NULL is not all bits zero, or if there are trap
        pointer representations , then the method won't work naturally. So I believe
        that in C89 it is not required to work.


        Comment

        • Joona I Palaste

          #5
          Re: struct named 0

          Michael Mair <Michael.Mair@i nvalid.invalid> scribbled the following:[color=blue]
          > Mohd Hanafiah Abdullah wrote:[color=green]
          >> Is the following code conformat to ANSI C?
          >>
          >> typedef struct {
          >> int a;
          >> int b;
          >> } doomdata;
          >>
          >> int main(void)
          >> {
          >> int x;
          >>
          >> x = (int)&((doomdat a*)0)->b;
          >> printf("x=%d\n" , x);
          >> return x;
          >> }
          >>
          >> The part,
          >> (int)&((doomdat a*)0)->b;
          >>
          >> is it conformant to ANSI C? What is it supposed to do?[/color][/color]
          [color=blue]
          > According to prior discussions, it is at least shady but
          > probably not conformant, depending on whether the address
          > 0 is dereferenced or not.
          > This is a version of the offsetof macro from <stddef.h>:
          > offsetof(doomda ta,b)
          > gives you the byte offset of b in struct doomsdata, that means
          > if we have
          > struct doomdata d;
          > unsigned char *p = (unsigned char *)&d;
          > then the address of d.b is p+offsetof(doom data,b).
          > In contrast to offsetof which expands to an expression of
          > type size_t, the above will give you an int.[/color]
          [color=blue]
          > Use offsetof.[/color]

          To be more specific, offsetof may be defined as the version mentioned by
          the OP, but it doesn't have to be. However, whatever offsetof is defined
          as, it is guaranteed to always be legal and valid code for that
          particular implementation. The version mentioned by the OP may or may
          not be valid and legal code, depending on the implementation.

          --
          /-- Joona Palaste (palaste@cc.hel sinki.fi) ------------- Finland --------\
          \-------------------------------------------------------- rules! --------/
          "The trouble with the French is they don't have a word for entrepreneur."
          - George Bush

          Comment

          • Jack Klein

            #6
            Re: struct named 0

            On Sun, 28 Nov 2004 11:26:06 +0100, Michael Mair
            <Michael.Mair@i nvalid.invalid> wrote in comp.lang.c:
            [color=blue]
            > Mohd Hanafiah Abdullah wrote:
            >[color=green]
            > > Is the following code conformat to ANSI C?
            > >
            > > typedef struct {
            > > int a;
            > > int b;
            > > } doomdata;
            > >
            > > int main(void)
            > > {
            > > int x;
            > >
            > > x = (int)&((doomdat a*)0)->b;
            > > printf("x=%d\n" , x);
            > > return x;
            > > }
            > >
            > > The part,
            > > (int)&((doomdat a*)0)->b;
            > >
            > > is it conformant to ANSI C? What is it supposed to do?[/color]
            >
            > According to prior discussions, it is at least shady but
            > probably not conformant, depending on whether the address
            > 0 is dereferenced or not.[/color]

            No it has undefined behavior, and has nothing to do with the "address
            0", but with a null pointer. C is defined in terms of an abstract
            machine, and in the abstract machine this expression dereferences a
            null pointer.
            [color=blue]
            > This is a version of the offsetof macro from <stddef.h>:
            > offsetof(doomda ta,b)
            > gives you the byte offset of b in struct doomsdata, that means
            > if we have
            > struct doomdata d;
            > unsigned char *p = (unsigned char *)&d;
            > then the address of d.b is p+offsetof(doom data,b).
            > In contrast to offsetof which expands to an expression of
            > type size_t, the above will give you an int.
            >
            > Use offsetof.[/color]

            Yes, indeed. The implementation' s offsetof() macro might indeed
            contain similar code, excepting the cast to int. But the
            implementation is not constrained to follow the rules of the abstract
            machine, only user programs are.
            [color=blue]
            > Cheers
            > Michael[/color]

            --
            Jack Klein
            Home: http://JK-Technology.Com
            FAQs for
            comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
            comp.lang.c++ http://www.parashift.com/c++-faq-lite/
            alt.comp.lang.l earn.c-c++

            Comment

            • Jack Klein

              #7
              Re: struct named 0

              On 28 Nov 2004 10:41:21 GMT, "S.Tobias"
              <siXtY@FamOuS.B edBuG.pAlS.INVA LID> wrote in comp.lang.c:
              [color=blue]
              > Mohd Hanafiah Abdullah <napi@cs.indian a.edu> wrote:
              >[color=green]
              > > typedef struct {
              > > int a;
              > > int b;
              > > } doomdata;[/color]
              >[color=green]
              > > (int)&((doomdat a*)0)->b;[/color]
              >[color=green]
              > > is it conformant to ANSI C?[/color]
              >
              > IMO no, because it doesn't point to any valid object, so
              > invokes UB.
              >
              > Question to others:
              > Would this be correct?
              > (int)&((doomdat a*)0)->a;[/color]

              Technically it is still undefined behavior, as the semantics of the
              expression dereference a null pointer.

              --
              Jack Klein
              Home: http://JK-Technology.Com
              FAQs for
              comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
              comp.lang.c++ http://www.parashift.com/c++-faq-lite/
              alt.comp.lang.l earn.c-c++

              Comment

              • Jack Klein

                #8
                Re: struct named 0

                On Sun, 28 Nov 2004 10:53:23 -0000, "Malcolm"
                <malcolm@55bank .freeserve.co.u k> wrote in comp.lang.c:
                [color=blue]
                >
                > "Mohd Hanafiah Abdullah" <napi@cs.indian a.edu> wrote[color=green]
                > >
                > > The part,
                > > (int)&((doomdat a*)0)->b;
                > >
                > > is it conformant to ANSI C? What is it supposed to do?
                > >[/color]
                > This is the offsetof() macro, which calculates the offset of a structure
                > member relative to the struct origin.[/color]

                No, it can't be the offsetof() macro. This expression specifically
                yields an int, whereas the offsetof() macro yields a size_t. This
                expression yields undefined behavior.
                [color=blue]
                > On most platforms it works, but it suffers a few problems on unusual
                > systems. For instance, if NULL is not all bits zero, or if there are trap
                > pointer representations , then the method won't work naturally. So I believe
                > that in C89 it is not required to work.[/color]

                When will people get it through their heads that it makes not a whit
                of difference whether all bits zero happens to be a representation of
                a null pointer on a particular platform?

                The correspondence between an integer constant expression evaluating
                to 0 and a null pointer is exactly the same as quite a few other
                constant expressions, that is something that is evaluated and
                substituted at compile-time and has nothing to do with run-time
                values.

                The conversion of a quoted string to an array of '\0' terminated
                values is a compile-time conversion.

                The conversion of escape sequences like '\n' and '\t' to their single
                character equivalents in string or character constants is a
                compile-time conversion.

                The conversion of an integer constant expression evaluating to 0, or
                such an expression cast to the type pointer-to-void, to a null pointer
                constant is a compile-time conversion, not a run-time one.

                If the one and only representation for a null pointer in a particular
                implementation is 0xDEADBEEF, and such a value is returned by a call
                to fopen(), for example, a comparison of that value against NULL or 0
                will still be true.

                --
                Jack Klein
                Home: http://JK-Technology.Com
                FAQs for
                comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
                comp.lang.c++ http://www.parashift.com/c++-faq-lite/
                alt.comp.lang.l earn.c-c++

                Comment

                • Jack Klein

                  #9
                  Re: struct named 0

                  On Sun, 28 Nov 2004 08:50:39 +0000 (UTC), napi@cs.indiana .edu (Mohd
                  Hanafiah Abdullah) wrote in comp.lang.c:
                  [color=blue]
                  >
                  > Is the following code conformat to ANSI C?
                  >
                  > typedef struct {
                  > int a;
                  > int b;
                  > } doomdata;
                  >
                  > int main(void)
                  > {
                  > int x;
                  >
                  > x = (int)&((doomdat a*)0)->b;[/color]

                  No, the line above invokes undefined behavior, because it dereferences
                  a null pointer.
                  [color=blue]
                  > printf("x=%d\n" , x);
                  > return x;
                  > }
                  >
                  > The part,
                  > (int)&((doomdat a*)0)->b;
                  >
                  > is it conformant to ANSI C? What is it supposed to do?[/color]

                  No, it is most certainly not conforming. It might have been written
                  as an example, or it might have been written by someone who doesn't
                  know that the offsetof(struct _type,member_na me) macro defined in
                  <stddef.h> does the same thing in a conforming manner.
                  [color=blue]
                  > Thanks for any tips.
                  >
                  > Napi[/color]

                  --
                  Jack Klein
                  Home: http://JK-Technology.Com
                  FAQs for
                  comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
                  comp.lang.c++ http://www.parashift.com/c++-faq-lite/
                  alt.comp.lang.l earn.c-c++

                  Comment

                  • Malcolm

                    #10
                    Re: struct named 0


                    "Jack Klein" <jackklein@spam cop.net> wrote[color=blue]
                    >[color=green][color=darkred]
                    > > > The part,
                    > > > (int)&((doomdat a*)0)->b;
                    > > >
                    > > > is it conformant to ANSI C? What is it supposed to do?
                    > > >[/color]
                    > > This is the offsetof() macro, which calculates the offset of a structure
                    > > member relative to the struct origin.[/color]
                    >
                    > No, it can't be the offsetof() macro. This expression specifically
                    > yields an int, whereas the offsetof() macro yields a size_t. This
                    > expression yields undefined behavior.
                    >[/color]
                    This is true. int is not guaranteed to be big enough to hold the offset of a
                    structure element (!).[color=blue]
                    >
                    > When will people get it through their heads that it makes not a whit
                    > of difference whether all bits zero happens to be a representation of
                    > a null pointer on a particular platform?
                    >[/color]
                    Unfortunately it does make a difference.
                    For instance consider

                    char **list = calloc(N, sizeof(char *));

                    for(i=0;i<N;i++ )
                    if( someconditon() )
                    list[i] = malloc(10);

                    for(i=0;i<N;i++ )
                    free(list[i]);

                    Also consider if a null pointer is cast to an integral type, or if a pointer
                    derived by adding an offset to the null pointer is cast to an integer. This
                    cast is a simple bitwise conversion, so results will differ on a platform on
                    which NULL is not all bits zero.

                    However char *ptr = 0; will always set ptr to NULL, regardless of whether
                    the null pointer is all bits zero. Here you are correct.



                    Comment

                    • Martin Ambuhl

                      #11
                      Re: struct named 0

                      Mohd Hanafiah Abdullah wrote:
                      [color=blue]
                      >
                      > The part,
                      > (int)&((doomdat a*)0)->b;
                      >
                      > is it conformant to ANSI C? What is it supposed to do?
                      >[/color]
                      #include <stdio.h>
                      #include <stddef.h>

                      typedef struct
                      {
                      int a;
                      int b;
                      } doomdata;

                      int main(void)
                      {
                      int x;
                      #if 0
                      /* mha: the following is an attempt to mimic offsetof on an
                      implementation not having offsetof in <stddef.h> */
                      x = (int) &((doomdata *) 0)->b;
                      #endif
                      x = offsetof(doomda ta, b);
                      printf("x=%d\n" , x);

                      return 0; /* mha: returning x, when x is not one
                      of 0, EXIT_SUCCESS, or EXIT_FAILURE
                      is at best implementation-defined */
                      }

                      Comment

                      • S.Tobias

                        #12
                        Re: struct named 0

                        Jack Klein <jackklein@spam cop.net> wrote:[color=blue]
                        > On 28 Nov 2004 10:41:21 GMT, "S.Tobias"
                        > <siXtY@FamOuS.B edBuG.pAlS.INVA LID> wrote in comp.lang.c:[color=green]
                        > > Mohd Hanafiah Abdullah <napi@cs.indian a.edu> wrote:[/color][/color]
                        [color=blue][color=green][color=darkred]
                        > > > typedef struct {
                        > > > int a;
                        > > > int b;
                        > > > } doomdata;[/color][/color][/color]
                        [color=blue][color=green]
                        > > Would this be correct?
                        > > (int)&((doomdat a*)0)->a;[/color][/color]
                        [color=blue]
                        > Technically it is still undefined behavior, as the semantics of the
                        > expression dereference a null pointer.[/color]

                        (This deserves a separate thread, but since I asked the above
                        question here, I'll continue here too.)

                        As I understand the expression constitutes an access to the structure
                        member.

                        1. Does a member access constitute an access to the *whole* structure?
                        eg.:
                        struct A { int i; int _i; };
                        struct B { int i; float f; };
                        struct A a = {0};
                        struct B *pb = (struct B*)&a;
                        pb->i; //UB?
                        (*pb).i; //UB?
                        Do I access the first int sub-object in `a' only, or do I access
                        the whole object `a'?

                        2. I see certain similarity between structs and arrays (in fact,
                        both are called "aggregates ").
                        Why is it that for array:
                        &a[5];
                        doesn't constitute object access (6.5.3.2#3), whereas for struct:
                        &s.m;
                        &ps->m;
                        the expressions do constitute access?
                        Why is the language designed like this?

                        --
                        Stan Tobias
                        mailx `echo siXtY@FamOuS.Be dBuG.pAlS.INVALID | sed s/[[:upper:]]//g`

                        Comment

                        • xarax

                          #13
                          Re: struct named 0

                          "Jack Klein" <jackklein@spam cop.net> wrote in message
                          news:ov3kq09rfb aenc41iqbaeuoup 5f87nq68e@4ax.c om...[color=blue]
                          > On Sun, 28 Nov 2004 11:26:06 +0100, Michael Mair
                          > <Michael.Mair@i nvalid.invalid> wrote in comp.lang.c:
                          >[color=green]
                          > > Mohd Hanafiah Abdullah wrote:
                          > >[color=darkred]
                          > > > Is the following code conformat to ANSI C?
                          > > >
                          > > > typedef struct {
                          > > > int a;
                          > > > int b;
                          > > > } doomdata;
                          > > >
                          > > > int main(void)
                          > > > {
                          > > > int x;
                          > > >
                          > > > x = (int)&((doomdat a*)0)->b;
                          > > > printf("x=%d\n" , x);
                          > > > return x;
                          > > > }
                          > > >
                          > > > The part,
                          > > > (int)&((doomdat a*)0)->b;
                          > > >
                          > > > is it conformant to ANSI C? What is it supposed to do?[/color]
                          > >
                          > > According to prior discussions, it is at least shady but
                          > > probably not conformant, depending on whether the address
                          > > 0 is dereferenced or not.[/color]
                          >
                          > No it has undefined behavior, and has nothing to do with the "address
                          > 0", but with a null pointer. C is defined in terms of an abstract
                          > machine, and in the abstract machine this expression dereferences a
                          > null pointer.[/color]
                          /snip/

                          It does not dereference any pointer. The & cancels out
                          the ->.

                          btw: If the dereference actually happened, how could the
                          compiler figure out the address of an int that was produced
                          by the dereference?



                          Comment

                          • Christian Bau

                            #14
                            Re: struct named 0

                            In article <cod91t$ihn$1@n ews7.svr.pol.co .uk>,
                            "Malcolm" <malcolm@55bank .freeserve.co.u k> wrote:
                            [color=blue]
                            > Also consider if a null pointer is cast to an integral type, or if a pointer
                            > derived by adding an offset to the null pointer is cast to an integer. This
                            > cast is a simple bitwise conversion, so results will differ on a platform on
                            > which NULL is not all bits zero.[/color]

                            Not quite; a conversion from a pointer type to an integer does whatever
                            the implementation thinks is a good idea; usually the bits of the
                            representation are copied unchanged, but that is not necessarily so.

                            In C99, there seems to be an actual requirement that casting an integer
                            zero to a pointer type will produce a null pointer. If null pointers
                            don't have all bits zero, and an integer 0 has all bits zero, and
                            converting an integer 0 to a pointer produces a null pointer, then logic
                            says that this conversion cannot leave the bits unchanged.

                            Comment

                            • Malcolm

                              #15
                              Re: struct named 0

                              "Christian Bau" <christian.bau@ cbau.freeserve. co.uk> wrote[color=blue]
                              >
                              > In C99, there seems to be an actual requirement that casting an integer
                              > zero to a pointer type will produce a null pointer. If null pointers
                              > don't have all bits zero, and an integer 0 has all bits zero, and
                              > converting an integer 0 to a pointer produces a null pointer, then logic
                              > says that this conversion cannot leave the bits unchanged.
                              >[/color]
                              But in this case we are not casting an integer 0 to a pointer, but a null
                              pointer to an integer.


                              Comment

                              Working...