Where do pointers point to?

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

    #16
    Re: Where do pointers point to?

    Michael Mair wrote:[color=blue]
    >
    > Lawrence Kirby wrote:
    >
    > [snip: void * vs char *]
    >[color=green]
    > > Yes, void * uses the same representation
    > > as pointers to character types.[/color]
    >
    > Are you sure of that?[/color]

    N869
    6.2.5 Types

    [#27] A pointer to void shall have the same representation
    and alignment requirements as a pointer to a character type.

    --
    pete

    Comment

    • Lawrence Kirby

      #17
      Re: Where do pointers point to?

      On Wed, 12 Jan 2005 12:45:59 +0100, Michael Mair wrote:
      [color=blue]
      > Lawrence Kirby wrote:
      >
      > [snip: void * vs char *]
      >[color=green]
      >> Yes, void * uses the same representation as pointers to character types.[/color]
      >
      > Are you sure of that? It is IMO logical but not necessary.[/color]

      6.2.5 says

      "A pointer to void shall have the same representation and alignment
      requirements as a pointer to a character type."
      [color=blue]
      > I am not sure where but a couple of months ago there was a discussion
      > where the example function execl() from the FAQ 5.2 (
      > http://www.eskimo.com/~scs/C-faq/q5.2.html ) was cited and where some
      > regulars stressed how important the cast (char *) is because execl is a
      > function with variable argument list and so we need to make sure that we
      > get (char *) NULL instead of plain (that is, (void *)) NULL.[/color]

      The case is important because NULL can be defined as, say, 0 i.e. have
      an integer type. This is certainly not guaranteed in any sense to have any
      representationa l equivalence to a pointer.

      There is a footnote for the standard text above that says:

      "The same representation and alignment requirements are meant to imply
      interchangeabil ity as arguments to functions, return values from
      functions, and members of unions."

      which brings up the question of whether you are guaranteed to be able to
      pass a void * argument to a function that requires a char *. As the text
      suggests you are pretty safe in doing this. OTOH the footnote is not
      normative and the text of the standard makes no absolute guarantee.

      Lawrence

      Comment

      • Eric Sosman

        #18
        Re: Where do pointers point to?

        Chris Croughton wrote:[color=blue]
        > On Tue, 11 Jan 2005 22:27:34 -0500, Eric Sosman
        > <esosman@acm-dot-org.invalid> wrote:
        >
        >[color=green]
        >>x-pander wrote:
        >>[color=darkred]
        >>>So how about the result of the following comparision,
        >>>which i think has a potential of effectively answering my original question:
        >>>
        >>>(int *)(char *)&v != &v[/color]
        >>
        >> Guaranteed to work (evaluating to 0) if `v' is an `int'.
        >>
        >> Potential undefined behavior if `v' is not an `int': the
        >>conversion of any arbitrary (object) pointer to `char*' is
        >>well-defined, but even so this does not justify the subsequent
        >>attempt to convert a non-`int*' to an `int*'. There are a few
        >>cases is which this is guaranteed to work (e.g., if `v' is a
        >>struct whose first element is an `int'), but in general the
        >>conversion is not safe.[/color]
        >
        >
        > Am I correct in thinking that conversion of a T* to a char* is always
        > safe (because sizeof char <= sizeof T for all types T) but the other way
        > round may not be? For instance, an int* might be constrained to have
        > some bits zero, so conversion to an int* with those bits set might
        > either cause a hardware exception or 'silently' set the bits to zero.[/color]

        Converting `AnyData*' to `char*' (and back) is always safe,
        but it's because the Standard says so, not because of the `sizeof'
        relation. The Standard does not sanction the conversion of
        `int*' to `short*', even when sizeof(short)<= sizeof(int). (I've
        never encountered a system where this relation didn't hold or
        where the conversion wouldn't work, but "There are more things
        on Heaven and Earth" and my experience is non-infinite ...)

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

        Comment

        • Michael Mair

          #19
          Re: Where do pointers point to?

          Lawrence Kirby wrote:[color=blue]
          > On Wed, 12 Jan 2005 12:45:59 +0100, Michael Mair wrote:
          >
          >[color=green]
          >>Lawrence Kirby wrote:
          >>
          >>[snip: void * vs char *]
          >>
          >>[color=darkred]
          >>>Yes, void * uses the same representation as pointers to character types.[/color]
          >>
          >>Are you sure of that? It is IMO logical but not necessary.[/color]
          >
          >
          > 6.2.5 says
          >
          > "A pointer to void shall have the same representation and alignment
          > requirements as a pointer to a character type."[/color]

          Thanks to you and pete :-)

          [color=blue][color=green]
          >>I am not sure where but a couple of months ago there was a discussion
          >>where the example function execl() from the FAQ 5.2 (
          >>http://www.eskimo.com/~scs/C-faq/q5.2.html ) was cited and where some
          >>regulars stressed how important the cast (char *) is because execl is a
          >>function with variable argument list and so we need to make sure that we
          >>get (char *) NULL instead of plain (that is, (void *)) NULL.[/color]
          >
          >
          > The case is important because NULL can be defined as, say, 0 i.e. have
          > an integer type. This is certainly not guaranteed in any sense to have any
          > representationa l equivalence to a pointer.
          >
          > There is a footnote for the standard text above that says:
          >
          > "The same representation and alignment requirements are meant to imply
          > interchangeabil ity as arguments to functions, return values from
          > functions, and members of unions."
          >
          > which brings up the question of whether you are guaranteed to be able to
          > pass a void * argument to a function that requires a char *. As the text
          > suggests you are pretty safe in doing this. OTOH the footnote is not
          > normative and the text of the standard makes no absolute guarantee.[/color]

          Essentially, this makes void * a pointer to a character type but
          for pointer arithmetics.
          For the above mentioned execl() call I could also use a terminating
          "(void *) 0" and be on the safe side.


          Thank you for clarifying
          Michael
          --
          E-Mail: Mine is an /at/ gmx /dot/ de address.

          Comment

          • CBFalconer

            #20
            Re: Where do pointers point to?

            Lawrence Kirby wrote:[color=blue]
            >[/color]
            .... snip ...[color=blue]
            >
            > which brings up the question of whether you are guaranteed to be
            > able to pass a void * argument to a function that requires a char *.
            > As the text suggests you are pretty safe in doing this. OTOH the
            > footnote is not normative and the text of the standard makes no
            > absolute guarantee.[/color]

            You can pass a void* to a function requiring any form of pointer,
            and the conversion is automatic. That is one of the points of
            having the void* type.

            --
            Chuck F (cbfalconer@yah oo.com) (cbfalconer@wor ldnet.att.net)
            Available for consulting/temporary embedded and systems.
            <http://cbfalconer.home .att.net> USE worldnet address!

            Comment

            • Michael Wojcik

              #21
              Re: Where do pointers point to?


              In article <41E548AE.27B0D E1F@yahoo.com>, CBFalconer <cbfalconer@yah oo.com> writes:[color=blue]
              > Lawrence Kirby wrote:[color=green]
              > >
              > > which brings up the question of whether you are guaranteed to be
              > > able to pass a void * argument to a function that requires a char *.
              > > As the text suggests you are pretty safe in doing this. OTOH the
              > > footnote is not normative and the text of the standard makes no
              > > absolute guarantee.[/color]
              >
              > You can pass a void* to a function requiring any form of pointer,
              > and the conversion is automatic.[/color]

              Not if the function is variadic, as is execl, the specific example
              here (or if there is no prototype in scope).

              We're agreed that, given the (POSIX) declaration of execl:

              extern int execl(const char *, ...);
              /* All parameters must be (possibly const-qualified) char *, and
              the last parameter must be a char* null pointer. */

              then:

              execl("foo", NULL);

              is not safe, because NULL might be defined as having integer type;
              and that:

              execl("foo", (char *)0);

              is safe, because that correctly passes a char* null pointer constant
              as the last variable parameter; but we're undecided on:

              execl("foo", (void *)0);

              because, as Lawrence points out, the "same size and representation"
              clause might leave some room for a conforming implementation to fail,
              and the footnote is non-normative.

              I *think* it'd be conforming, albeit excruciatingly perverse, for an
              implementation to say that, although char* and void* have the same
              representation, char* parameters are passed in, say, registers, while
              void* parameters are passed on the stack; and that this applies even
              to, say, the first few parameters to a variadic function. But I could
              well be wrong.

              Perhaps the committee should have defined an "object pointer promotion"
              for variadic functions: just as integer and floating-point promotions
              happen for variable parameters, all object pointers could be promoted
              to void* when passed as variable parameters (or in any case when no
              prototype is in scope). But they didn't.

              --
              Michael Wojcik michael.wojcik@ microfocus.com

              How can I sing with love in my bosom?
              Unclean, immature and unseasonable salmon. -- Basil Bunting

              Comment

              • x-pander

                #22
                Re: Where do pointers point to?

                > int v;[color=blue]
                > (void*)(char*)& v == (void*)&v;
                >
                > I still don't see it (maybe it's obvious, but it's still early morning
                > for me and a coffee didn't help). The Standard int 6.3.2.3 (Conversions
                > ...
                > Pointers) only demands that (subject to alignment) conversions between
                > pointer types are reversible. However I don't see how you can infer
                > from it that single int*->void* conversion must yield the same value
                > as double conversion int*->char*->void*. How do you do it?
                >
                > Where exactly is it written that the result of pointer conversion
                > (provided it doesn't invoke UB) must point to the same location
                > as the original pointer?[/color]

                Consider the following function:

                void memset1(char *p, int c, int n)
                {
                while(n-->0) *p++ = c;
                }

                Now the call:
                memset1((char *)&v, 0, sizeof(v));
                is guaranteed to work as desired, by 6.3.2.3 p7 (C99).

                Now consider:

                void memset2(void *p, int c, int n)
                {
                while(n-->0) *((char *)p)++ = c;
                }

                memset2(&v, 0, sizeof(v));

                What happens here is:
                1. 'int *' is automatically converted to 'void *' on function call
                2. 'void *' is converted to 'char *' inside a function

                Which part(s) of the C99 standard (if any?) guarantee that (char *)(void
                *)&v equals to (char *)&v, that is to the lowest addresed byte of object v ?


                Comment

                • Eric Sosman

                  #23
                  Re: Where do pointers point to?

                  x-pander wrote:[color=blue]
                  > [...]
                  > Now consider:
                  >
                  > void memset2(void *p, int c, int n)
                  > {
                  > while(n-->0) *((char *)p)++ = c;
                  > }[/color]

                  When my compiler considered this, it said

                  "foo.c", line 4: warning: a cast does not
                  yield an lvalue

                  See also Question 4.5 in the comp.lang.c Frequently
                  Asked Question (FAQ) list


                  [color=blue]
                  > What happens here is: [...][/color]

                  .... entirely up to the implementation. After issuing
                  the required diagnostic for the illegal construct, it
                  can then choose to interpret that construct in any way
                  it pleases.

                  --
                  Eric.Sosman@sun .com

                  Comment

                  • x-pander

                    #24
                    Re: Where do pointers point to?

                    >> void memset2(void *p, int c, int n)[color=blue][color=green]
                    >> {
                    >> while(n-->0) *((char *)p)++ = c;
                    >> }[/color]
                    >
                    > When my compiler considered this, it said
                    >
                    > "foo.c", line 4: warning: a cast does not
                    > yield an lvalue
                    >[/color]

                    yea, my bad, but that was not what the question was all about
                    let me change the implemetation to:

                    void memset2(void *p, int c, int n)
                    {
                    while(n-->0) ((char *)p)[n] = c;
                    }

                    now it should be valid and the original question remains unchanged


                    Comment

                    • Eric Sosman

                      #25
                      Re: Where do pointers point to?

                      x-pander wrote:[color=blue]
                      >
                      > let me change the implemetation to:
                      >
                      > void memset2(void *p, int c, int n)
                      > {
                      > while(n-->0) ((char *)p)[n] = c;
                      > }
                      >
                      > now it should be valid and the original question remains unchanged[/color]

                      For our reference, the original question was[color=blue]
                      >
                      > Which part(s) of the C99 standard (if any?) guarantee that
                      > (char *)(void *)&v equals to (char *)&v, that is to the
                      > lowest addresed byte of object v ?[/color]

                      6.3.2.3/7 covers the conversion to `char*' and the "lowest
                      addressed" piece. 6.3.2.3/1 covers the conversion to and
                      from `void*'. Or have I overlooked a subtlety?

                      --
                      Eric.Sosman@sun .com

                      Comment

                      • x-pander

                        #26
                        Re: Where do pointers point to?

                        >> Which part(s) of the C99 standard (if any?) guarantee that[color=blue][color=green]
                        >> (char *)(void *)&v equals to (char *)&v, that is to the
                        >> lowest addresed byte of object v ?[/color]
                        >
                        > 6.3.2.3/7 covers the conversion to `char*' and the "lowest
                        > addressed" piece. 6.3.2.3/1 covers the conversion to and
                        > from `void*'. Or have I overlooked a subtlety?[/color]

                        True, but I dont see how those can answer "the question". Here is how i read
                        that:

                        6.3.2.3/7: (char *)&v -> points to the lowest addressed byte of an object
                        pointed by '&v' which is of type 'int'

                        6.3.2.3/1: (void *)&v -> valid conversion, only guarantee: if this pointer
                        is converted back to (int *) it equals to '&v'
                        6.3.2.3/7 (char *)(void *)&v -> valid conversion, points to the lowest
                        addresed byte of an object pointed by '(void *)&v' which is of type 'void'

                        Now, what is the lowest addressed byte of an object of type 'void' ?
                        6.2.5/19: "The void type comprises an empty set of values; it is an
                        incomplete type that cannot be completed"

                        From that definition I would say that an object of type void does not have
                        any storage or representation associated with it, so the concept of it's
                        lowest addressed byte is not quite sensible.

                        So, where do I go from here to find an answer to the qustion at the top of
                        this post?


                        Comment

                        • Christian Bau

                          #27
                          Re: Where do pointers point to?

                          In article <cs21on$27hl$1@ mamut1.aster.pl >,
                          "x-pander" <ngclc@pitek.eu .org> wrote:
                          [color=blue][color=green]
                          > > It points to the "first" byte. The C Standard doesn't say anything about
                          > > addresses.[/color]
                          >
                          > Actually it does:
                          > C99: 6.3.2.3.7
                          > "When a pointer to an object is converted to a pointer to a character type,
                          > the result points to the lowest addressed byte of the object. Successive
                          > increments of the result, up to the size of the object, yield pointers to
                          > the remaining bytes of the object."
                          >[color=green]
                          > > You need to make it run on littleendian hardware.
                          > > You have the source code to the compiler. Instead of changing 10 million
                          > > lines of code, change the compiler so that the "first" byte is at a
                          > > higher address than the last byte; where "p++;" would usually be
                          > > translated into a hardware instruction that adds sizeof (*p), it will be
                          > > translated to a hardware instruction that subtracts sizeof (*p). Pointer
                          > > comparisons say that p < q if a hardware compare instruction says p > q
                          > > and so on. Now a pointer always points to the highest addressed byte,
                          > > and it is completely conforming and invisible to the programmer.[/color]
                          >
                          > An example situation in described system could be:
                          >
                          > int x;
                          > &x == 0x4003
                          > (void *)&x == 0x4003
                          > (char *)&x == 0x4000
                          > (void *)(char *)&x = 0x4000[/color]

                          No; (char *)&x would be == 0x4003. The first byte would be at address
                          0x4003, the second byte at address 0x4002, and so on. ((char *) &x) + 1
                          would be == 0x4002. If you compare ((char *) &x) < ((char *) &x) + 1,
                          the result is true (1).

                          Comment

                          • Christian Bau

                            #28
                            Re: Where do pointers point to?

                            In article <34kh06F4ai3f9U 1@individual.ne t>,
                            Michael Mair <Michael.Mair@i nvalid.invalid> wrote:
                            [color=blue]
                            > Lawrence Kirby wrote:
                            >
                            > [snip: void * vs char *]
                            >[color=green]
                            > > Yes, void * uses the same representation as pointers to character types.[/color]
                            >
                            > Are you sure of that? It is IMO logical but not necessary.
                            >
                            > I am not sure where but a couple of months ago there was a
                            > discussion where the example function execl() from the FAQ 5.2
                            > ( http://www.eskimo.com/~scs/C-faq/q5.2.html ) was cited and
                            > where some regulars stressed how important the cast (char *)
                            > is because execl is a function with variable argument list
                            > and so we need to make sure that we get (char *) NULL instead
                            > of plain (that is, (void *)) NULL.[/color]

                            The problem here is probably that NULL itself could be defined as 0 or
                            0L or 0LL or ((void *) 0), for example, so it could have type int, long,
                            long long, or void*. If you assign NULL to a pointer variable, it will
                            be converted to a null pointer of the right type, no problem. But if you
                            pass NULL to a function with variable argument list, you have no idea
                            what type it actually is. (char *) NULL or (void *) NULL should both
                            work fine.

                            Comment

                            • Keith Thompson

                              #29
                              Re: Where do pointers point to?

                              mwojcik@newsguy .com (Michael Wojcik) writes:
                              [...][color=blue]
                              > I *think* it'd be conforming, albeit excruciatingly perverse, for an
                              > implementation to say that, although char* and void* have the same
                              > representation, char* parameters are passed in, say, registers, while
                              > void* parameters are passed on the stack; and that this applies even
                              > to, say, the first few parameters to a variadic function. But I could
                              > well be wrong.[/color]

                              I think you're right.

                              C99 6.3.5p26 says:

                              A pointer to void shall have the same representation and alignment
                              requirements as a pointer to a character type.

                              and a footnote says:

                              The same representation and alignment requirements are meant to
                              imply interchangeabil ity as arguments to functions, return values
                              from functions, and members of unions.

                              But since footnotes are non-normative, an excruciatingly perverse
                              implementation could ignore it.

                              --
                              Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                              San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
                              We must do something. This is something. Therefore, we must do this.

                              Comment

                              • S.Tobias

                                #30
                                Re: Where do pointers point to?

                                Eric Sosman <eric.sosman@su n.com> wrote:[color=blue]
                                > x-pander wrote:[/color]
                                [color=blue]
                                > For our reference, the original question was[color=green]
                                > >
                                > > Which part(s) of the C99 standard (if any?) guarantee that
                                > > (char *)(void *)&v equals to (char *)&v, that is to the
                                > > lowest addresed byte of object v ?[/color][/color]

                                I claim that in this sub-thread my question was "more original": :-)

                                Where exactly is it written that the result of pointer conversion
                                (provided it doesn't invoke UB) must point to the same location
                                as the original pointer?
                                [color=blue]
                                > 6.3.2.3/7 covers the conversion to `char*' and the "lowest
                                > addressed" piece. 6.3.2.3/1 covers the conversion to and
                                > from `void*'. Or have I overlooked a subtlety?[/color]

                                Only of char* the Standard says that explicitly.


                                Suppose an implementation on which alignment is not an issue, and pointers
                                are represented as unsigned integers, conversion between pointer and
                                integer type is natural (ie. (unsigned)ptr0x ABCD == 0xABCD),
                                and representation of a pointer to any type is also natural (ie.
                                a pointer to any type that has a value 0xABCD points to an object
                                whose lowest addressed byte is at the address 0xABCD). Null pointer
                                for any type is represented as 0x0.

                                Now, with each pointer conversion associate an arbitrary number in
                                such a way that a reverse conversion has an associated opposite number.
                                With conversions involving char* the associated number(s) is 0 (zero).

                                Example:
                                (int*)->(long*) 3 (long*)->(int*) -3
                                (short*)->(int*) -2 (int*)->(short*) 2
                                (void*)->(long*) 5 (long*)->(void*) -5
                                (char*)->(int*) 0 (int*)->(char*) 0
                                (char*)->(void*) 0 (void*)->(char*) 0

                                Now, the pointer conversion is defined so that in addition to
                                changing the type, the associated conversion number is added
                                to the pointer (integer) value (in arithmetic sense, so for example,
                                when converting from long* to int*, the result will point three
                                bytes before the original pointer).

                                When the "shift" hits the upper or lower boundary, it wraps around,
                                skipping zero. (This way all null pointers are converted into null
                                pointers; though I'm not sure it's really necessary.)

                                Would such an implementation break the Standard?

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

                                Comment

                                Working...