pointer-in-array test

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

    #31
    Re: pointer-in-array test

    Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> writes:
    [color=blue]
    > Dik T. Winter wrote:
    >[color=green]
    >> In article <1133145.9pkQ6i reiI@holzmayer. ifr.rt>
    >> holzmayer.bernh ard@deadspam.co m writes: ...[color=darkred]
    >> > What about this solution:
    >> > int ptrInArrSafe(T *p,T *a,int max)
    >> > /* check whether p points to an element of a[max] */
    >> > {
    >> > long px = (long)p;
    >> > long ax = (long)a;
    >> > if (px<ax) return 0; /*out*/
    >> > if (px> (long)&a[max-1]) return 0; /* out */
    >> > if ( (px-ax) % sizeof(T)) return 0; /* not at element
    >> > start*/
    >> > return 1; /* in and on element start */
    >> > }
    >> >
    >> > compiles, links, runs without problems with my gcc.
    >> > And, as far as I remember, it's legal, to compare pointers
    >> > after conversion to long.[/color]
    >>
    >> But the result is implementation defined. I know of at least one
    >> system where it will fail to give the correct answer, then T is
    >> char. For instance:
    >> (long)(a + 7) > (long)(a + 8)
    >> when a is an array of type char.[/color]
    >
    > That's not the same.
    > Would you please try the following:
    > (long)(&a[7]) < (long)(&a[8])[/color]

    The only difference between these expressions is that the first uses the
    `>' operator, while the second uses the `<' operator. But `(long)(a+7)'
    is exactly the same as `(long)(&a[7])' (likewise if both 7s are replaced
    by 8s).

    Also, trying something (in the sense of compiling and running it and
    observing what it does) is a very flawed way to determine if something
    is correct, as it does not necessarily give the right answer.
    [color=blue]
    > this should give the correct result.[/color]

    The result of the conversion to `long' is implementation-defined, so it
    cannot be correct on all possible implementations .

    If `long' cannot represent the pointer value, the behavior is undefined.
    [color=blue]
    > Reason for your strange behaviour is possibly the implicite type
    > cast,[/color]

    C does not have implicit type casts. You mean conversion. :)
    [color=blue]
    > which converts a before adding.[/color]

    There's no conversion before adding. This is the `+' operator between a
    pointer and an integer type, which results in a pointer type.
    [color=blue]
    > Instead, the later version increments a as a pointer and then converts
    > it.[/color]

    So does the first.

    Martin


    --
    ,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
    / ,- ) http://www.zero-based.org/ ((_/)o o(\_))
    \ `-' `-'(. .)`-'
    `-. Debian, a variant of the GNU operating system. \_/

    Comment

    • Martin Dickopp

      #32
      Re: pointer-in-array test

      Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> writes:
      [color=blue]
      > Christian Bau wrote:
      >[color=green]
      >> In article <1133145.9pkQ6i reiI@holzmayer. ifr.rt>,
      >> Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:
      >>[color=darkred]
      >>> Sorry,
      >>> pardon me for not checking my code intensively enough.
      >>> I just checked with a 'gcc -pedantic' which didn't throw an error
      >>> :(
      >>>
      >>> What about this solution:
      >>> int ptrInArrSafe(T *p,T *a,int max)
      >>> /* check whether p points to an element of a[max] */
      >>> {
      >>> long px = (long)p;
      >>> long ax = (long)a;
      >>> if (px<ax) return 0; /*out*/
      >>> if (px> (long)&a[max-1]) return 0; /* out */
      >>> if ( (px-ax) % sizeof(T)) return 0; /* not at element
      >>> start*/
      >>> return 1; /* in and on element start */
      >>> }
      >>>
      >>> compiles, links, runs without problems with my gcc.
      >>> And, as far as I remember, it's legal, to compare pointers after
      >>> conversion to long.[/color]
      >>
      >> It just isn't guaranteed to produce any meaningful result.[/color]
      >
      > Why. Please give arguments.[/color]

      6.3.2.3#6:
      | Any pointer type may be converted to an integer type. Except as
      | previously specified, the result is implementation-defined. If the
      | result cannot be represented in the integer type, the behavior is
      | undefined. The result need not be in the range of values of any
      | integer type.

      Martin


      --
      ,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
      / ,- ) http://www.zero-based.org/ ((_/)o o(\_))
      \ `-' `-'(. .)`-'
      `-. Debian, a variant of the GNU operating system. \_/

      Comment

      • Bernhard Holzmayer

        #33
        Re: pointer-in-array test

        Irrwahn Grausewitz wrote:
        [color=blue]
        > Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:
        > <snip>[color=green]
        >>After a close look to K&R 5.3 and additional sources, I'd like
        >>to improve the above a little. What about the following modified
        >>version:
        >>
        >> int ptrInArrSafe(T *p,T *a,int max)
        >> /* check whether p points to an element of a[max] */
        >> {
        >> long index;
        >>
        >> /* as long as a points to a valid array, this is a legal
        >> test for the lower boundary*/
        >> if (p<a) return 0; /*out */[/color]
        >
        > If p and a didn't point into (or one past) the same array in
        > the first place, you already invoked undefined behaviour here
        > (C99 6.5.8#5). All bets off.[/color]
        What a pity. Then, I guess, it's up to the caller of the function,
        to make sure p is a valid pointer ;-)[color=blue]
        >[color=green]
        >> /* evaluation of element's address is valid for all
        >> elements
        >>including the virtual last+1 element, though its content may not
        >>be retrieved, comparison is legal test for upper boundary */
        >> if (!(p<&a[max])) return 0; /* out */[/color]
        >
        > Ditto.[/color]
        You trapped me.[color=blue]
        >[color=green]
        >> /* now we can be sure that we are inside array, because
        >>standard requires that array is in a logically "dense" order, from
        >>point of logical addresses they must be accessible in ascending
        >>order */
        >>
        >> index = (long)(p - a);[/color]
        >
        > Forget about the cast. Declare index as ptrdiff_t instead.[/color]
        Sure. Anyhow, I just forgot to remove the line after I realized that
        it could be done without explicite cast.[color=blue]
        >[color=green]
        >> /* as far as I understand, it's possible that p-a returns
        >>the difference in multiples of sizeof(T), so that if element size
        >>were 2, a[2]-a[1] would give 1 instead of 2.[/color]
        >
        > That's not only possible, it's /required/ for a conforming
        > implementation to behave like this (C99 6.5.6#9): pointer
        > subtraction always yields values in units of element size.[/color]
        I read this, and got it like you. However, it's not my experience
        when working with real compilers.
        [color=blue]
        >[color=green]
        >>Although I never found a compiler doing this,[/color]
        >
        > Then you only found non-conforming compilers up until now.[/color]
        one is gcc 2.95.3, tried on a struct with sizeof(T)==8[color=blue]
        >[color=green]
        >>I replace sizeof(T) by
        >>a method which should work in both cases. */
        >> if ( (p-a) % (&a[1]-&a[0]))[/color]
        >
        > Since &a[1]-&a[0] (==a+1-a) always yields 1, the condition
        > is always false.[/color]

        However, with gcc, where p-a is 24, if p==&a[3], and &a[1]-&a[0]
        ==8, this returns true, if p points to an element between
        boundaries, so it's useful in both situations on both types of
        compilers... which was the intention.[color=blue]
        >[color=green]
        >> return 0; /* not at element boundary*/
        >>
        >> return 1; /* in and on element boundary */
        >> }[/color]
        >
        > End of the story: if you ever need to verify if a specific
        > pointed-to object is part of a certain array, carry around
        > the array length plus indices and compare these instead of
        > some 'raw' pointers. And, IMHO, if one feels the need to
        > perform the operation desired by the OP, one should first
        > rethink the algorithm, because it's most probably broken by
        > design.[/color]
        I agree.[color=blue]
        >
        > HTH
        > Regards[/color]

        I learned a bit. Thanks.
        Bernhard

        Comment

        • Martin Dickopp

          #34
          Re: pointer-in-array test

          Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> writes:
          [color=blue]
          > 1) Isn't it correct, that long has to be of the size to hold any
          > pointer, so that a conversion:
          > (pType *) --> (void *) ---> (long)
          > and vice versa is legal?[/color]

          No. In C99, you have the optional integer types `intptr_t' and
          `uintptr_t' which can represent all values of `void *' if they exist at
          all. In C89, no integer type is guaranteed to have this property.

          Even if a suitable integer type exists, the conversion is not guaranteed
          to preserve the ordering, i.e. while `&a[0] < &a[1]' is always true,
          `(long)(&a[0]) < (long)(&a[1])' need not be, even if `long' can
          represent the pointer values.
          [color=blue]
          > 2) Isn't it correct, that arrays must have their elements arranged
          > subsequently, so that array == &array[0] and
          > &array[1]>&array[0] are valid?[/color]

          Yes. Both expression evaluate to true (i.e. 1).

          Martin


          --
          ,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
          / ,- ) http://www.zero-based.org/ ((_/)o o(\_))
          \ `-' `-'(. .)`-'
          `-. Debian, a variant of the GNU operating system. \_/

          Comment

          • Irrwahn Grausewitz

            #35
            Re: pointer-in-array test

            Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:[color=blue]
            >pete wrote:[/color]
            <snip>[color=blue][color=green]
            >> N869
            >> 6.3.2.3 Pointers
            >> [#6] Any pointer type may be converted to an integer
            >> [#type.
            >> Except as previously specified, the result
            >> is
            >> implementation-defined. If the result cannot be
            >> represented
            >> in the integer type, the behavior is undefined. The
            >> result need not be in the range of values of any integer
            >> type.
            >>[/color]
            >
            >1) Isn't it correct, that long has to be of the size to hold any
            >pointer, so that a conversion:
            >(pType *) --> (void *) ---> (long)
            >and vice versa is legal?[/color]

            As is obvious from above quote: no.
            [color=blue]
            >2) Isn't it correct, that arrays must have their elements arranged
            >subsequently , so that array == &array[0] and
            >&array[1]>&array[0] are valid?[/color]

            Yes, err no, it's correct.

            Regards
            --
            Irrwahn Grausewitz (irrwahn33@free net.de)
            welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
            clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
            clc OT guide : http://benpfaff.org/writings/clc/off-topic.html

            Comment

            • Irrwahn Grausewitz

              #36
              Re: pointer-in-array test

              Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:[color=blue]
              >Bernhard Holzmayer wrote:[/color]
              <snip>[color=blue]
              >Keith, would this hold on your Cray with the strange CHAR
              >representation , that p-a still returns a reasonable result?
              >*/[color=green]
              >> if ( (p-a) % (&a[1]-&a[0]))
              >> return 0; /* not at element boundary*/[/color][/color]
              <snip>

              Well, I'm not Keith, but for two pointers p and a the expression
              (p-a) gives a reasonable result if, and only if, both point to
              elements of (or one past) the same array object:

              ISO/IEC 9899:1999 (E)
              6.5.6 Additive operators
              [...]
              9 When two pointers are subtracted, both shall point to elements of
              the same array object, or one past the last element of the array
              object; the result is the difference of the subscripts of the two
              array elements. The size of the result is implementation-defined,
              and its type (a signed integer type) is ptrdiff_t defined in the
              <stddef.h> header. If the result is not representable in an object
              of that type, the behavior is undefined. In other words, if the
              expressions P and Q point to, respectively, the i-th and j-th
              elements of an array object, the expression (P)-(Q) has the value
              i-j provided the value fits in an object of type ptrdiff_t.
              Moreover, if the expression P points either to an element of an
              array object or one past the last element of an array object, and
              the expression Q points to the last element of the same array
              object, the expression ((Q)+1)-(P) has the same value as
              ((Q)-(P))+1 and as -((P)-((Q)+1)), and has the value zero if the
              expression P points one past the last element of the array object,
              even though the expression (Q)+1 does not point to an element of
              the array object.

              HTH
              Regards
              --
              Irrwahn Grausewitz (irrwahn33@free net.de)
              welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
              clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
              clc OT guide : http://benpfaff.org/writings/clc/off-topic.html

              Comment

              • Irrwahn Grausewitz

                #37
                Re: pointer-in-array test

                Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:[color=blue]
                >Irrwahn Grausewitz wrote:
                >[color=green]
                >> Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:[/color][/color]
                <snip>[color=blue][color=green][color=darkred]
                >>> if (p<a) return 0; /*out */[/color]
                >>
                >> If p and a didn't point into (or one past) the same array in
                >> the first place, you already invoked undefined behaviour here
                >> (C99 6.5.8#5). All bets off.[/color]
                >What a pity. Then, I guess, it's up to the caller of the function,
                >to make sure p is a valid pointer ;-)[/color]
                <snip>

                That's indeed the best solution. ;-)
                [color=blue][color=green][color=darkred]
                >>> /* as far as I understand, it's possible that p-a returns
                >>>the difference in multiples of sizeof(T), so that if element size
                >>>were 2, a[2]-a[1] would give 1 instead of 2.[/color]
                >>
                >> That's not only possible, it's /required/ for a conforming
                >> implementation to behave like this (C99 6.5.6#9): pointer
                >> subtraction always yields values in units of element size.[/color]
                >I read this, and got it like you. However, it's not my experience
                >when working with real compilers.
                >[color=green][color=darkred]
                >>>Although I never found a compiler doing this,[/color]
                >>
                >> Then you only found non-conforming compilers up until now.[/color]
                >one is gcc 2.95.3, tried on a struct with sizeof(T)==8[/color]
                <snip>

                Uck. IIRC gcc 2.xx is indeed broken in several ways.
                [color=blue][color=green][color=darkred]
                >>> if ( (p-a) % (&a[1]-&a[0]))[/color]
                >>
                >> Since &a[1]-&a[0] (==a+1-a) always yields 1, the condition
                >> is always false.[/color]
                >
                >However, with gcc, where p-a is 24, if p==&a[3], and &a[1]-&a[0]
                >==8, this returns true, if p points to an element between
                >boundaries, so it's useful in both situations on both types of
                >compilers... which was the intention.[/color]
                <snip>

                Well, I see your point, but IMHO, if one really has to cater for
                broken implementations , I'd try to deal with it in the preprocessing
                stage in RealWorld[tm] code (not including throw-away NG examples,
                of course).
                [color=blue]
                >I learned a bit. Thanks.[/color]

                </me listening to distant barking sounds>
                Hopefully I didn't screw up something this time, but the pack will
                eventually jump on it and correct it anyway. ;-)

                Regards
                --
                Irrwahn Grausewitz (irrwahn33@free net.de)
                welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
                clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
                clc OT guide : http://benpfaff.org/writings/clc/off-topic.html

                Comment

                • Bernhard Holzmayer

                  #38
                  Re: pointer-in-array test

                  Irrwahn Grausewitz wrote:
                  [color=blue]
                  > SO/IEC 9899:1999 (E)
                  > 6.5.6 Additive operators
                  > [...]
                  > 9 When two pointers are subtracted, both shall point to elements
                  > of
                  > the same array object, or one past the last element of the
                  > array[/color]

                  Here it reads "shall", not "must".
                  That's what I have in mind, and what one can read in several
                  locations where pointers and pointer arithmetics are handled.

                  Either ISO should be clearer here, if this means optional like
                  undefined behaviour.

                  Otherwise, if it is written on purpose, it's an implicite statement
                  that at least one of the pointers may point elsewhere.

                  SCNR,
                  Bernhard

                  Comment

                  • Dik T. Winter

                    #39
                    Re: pointer-in-array test

                    In article <12289777.uitlg sWDZv@holzmayer .ifr.rt> holzmayer.bernh ard@deadspam.co m writes:[color=blue]
                    > Dik T. Winter wrote:[/color]
                    ....[color=blue][color=green]
                    > > But the result is implementation defined. I know of at least one
                    > > system where it will fail to give the correct answer, then T is
                    > > char. For instance:
                    > > (long)(a + 7) > (long)(a + 8)
                    > > when a is an array of type char.[/color]
                    >
                    > That's not the same.[/color]

                    What is the difference?
                    [color=blue]
                    > Would you please try the following:
                    > (long)(&a[7]) < (long)(&a[8])[/color]

                    Returns false on that system.
                    [color=blue]
                    > this should give the correct result.[/color]

                    Which is the correct result on that system.
                    [color=blue]
                    > Reason for your strange behaviour is possibly the implicite type
                    > cast, which converts a before adding.[/color]

                    No, that is *not* the reason, because there is no implicit type cast.
                    [color=blue]
                    > Instead, the later version increments a as a pointer and then
                    > converts it.[/color]

                    As does the first version. But to clarify, on that system a pointer
                    (and a long) are 64 bits. In a pointer the lower 48 bits are the
                    word pointer (a word is also 64 bits), the upper 16 bits are a
                    relative byte pointer within a word. Casting a pointer to long
                    performs no conversion at all.
                    --
                    dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
                    home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

                    Comment

                    • Irrwahn Grausewitz

                      #40
                      Re: pointer-in-array test

                      Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:[color=blue]
                      >Irrwahn Grausewitz wrote:
                      >[color=green]
                      >> SO/IEC 9899:1999 (E)
                      >> 6.5.6 Additive operators
                      >> [...]
                      >> 9 When two pointers are subtracted, both shall point to elements
                      >> of
                      >> the same array object, or one past the last element of the
                      >> array[/color]
                      >
                      >Here it reads "shall", not "must".
                      >That's what I have in mind, and what one can read in several
                      >locations where pointers and pointer arithmetics are handled.
                      >
                      >Either ISO should be clearer here, if this means optional like
                      >undefined behaviour.
                      >
                      >Otherwise, if it is written on purpose, it's an implicite statement
                      >that at least one of the pointers may point elsewhere.[/color]

                      "Shall" is Standardese for: "must, under all circumstances,
                      otherwise demons might fly out of your nose". :-)

                      Or, as the authors of the standard put it:

                      ISO/IEC 9899:1999 (E)
                      4. Conformance
                      1 In this International Standard, "shall" is to be interpreted as
                      a requirement on an implementation or on a program; conversely,
                      "shall not" is to be interpreted as a prohibition.

                      Regards.
                      --
                      Irrwahn Grausewitz (irrwahn33@free net.de)
                      welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
                      clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
                      clc OT guide : http://benpfaff.org/writings/clc/off-topic.html

                      Comment

                      • Martin Dickopp

                        #41
                        Re: pointer-in-array test

                        Irrwahn Grausewitz <irrwahn33@free net.de> writes:
                        [color=blue]
                        > Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:[color=green]
                        >>Irrwahn Grausewitz wrote:
                        >>[color=darkred]
                        >>> Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:
                        >>>> /* as far as I understand, it's possible that p-a returns
                        >>>>the difference in multiples of sizeof(T), so that if element size
                        >>>>were 2, a[2]-a[1] would give 1 instead of 2.[/color][/color][/color]
                        ^^^^^^^^^
                        I assume you mean `&a[2]-&a[1]' here? Otherwise, the statement doesn't
                        make much sense in this context, as the /contents/ of the array `a' are
                        not necessarily correlated to the size of its elements.
                        [color=blue][color=green][color=darkred]
                        >>> That's not only possible, it's /required/ for a conforming
                        >>> implementation to behave like this (C99 6.5.6#9): pointer
                        >>> subtraction always yields values in units of element size.[/color]
                        >>I read this, and got it like you. However, it's not my experience
                        >>when working with real compilers.
                        >>[color=darkred]
                        >>>>Although I never found a compiler doing this,
                        >>>
                        >>> Then you only found non-conforming compilers up until now.[/color]
                        >>one is gcc 2.95.3, tried on a struct with sizeof(T)==8[/color]
                        > <snip>
                        >
                        > Uck. IIRC gcc 2.xx is indeed broken in several ways.[/color]

                        While gcc 2.95.3 was indeed broken in some ways, it wasn't *that*
                        broken. :) In fact, I have sucessfully used pointer arithmentic with
                        more or less every gcc version since at least 2.6.3.

                        There's likely a different explanation for Bernhard's observation, e.g.
                        UB at a different position in the program.

                        Martin


                        --
                        ,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
                        / ,- ) http://www.zero-based.org/ ((_/)o o(\_))
                        \ `-' `-'(. .)`-'
                        `-. Debian, a variant of the GNU operating system. \_/

                        Comment

                        • Martin Dickopp

                          #42
                          Re: pointer-in-array test

                          Irrwahn Grausewitz <irrwahn33@free net.de> writes:
                          [color=blue]
                          > Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:[color=green]
                          >>Irrwahn Grausewitz wrote:
                          >>[color=darkred]
                          >>> ISO/IEC 9899:1999 (E)
                          >>> 6.5.6 Additive operators
                          >>> [...]
                          >>> 9 When two pointers are subtracted, both shall point to elements
                          >>> of the same array object, or one past the last element of the
                          >>> array[/color]
                          >>
                          >>Here it reads "shall", not "must".[/color]
                          >
                          > "Shall" is Standardese for: "must, under all circumstances,
                          > otherwise demons might fly out of your nose". :-)
                          >
                          > Or, as the authors of the standard put it:
                          >
                          > ISO/IEC 9899:1999 (E)
                          > 4. Conformance
                          > 1 In this International Standard, "shall" is to be interpreted as
                          > a requirement on an implementation or on a program; conversely,
                          > "shall not" is to be interpreted as a prohibition.[/color]

                          The standard then goes on:
                          | 2 If a "shall" or "shall not" requirement that appears outside of
                          | a constraint is violated, the behavior is undefined.

                          This is the case here, as 6.5.6#9 is not a constraint.

                          Undefined behavior is defined in 3.4.3:
                          | 1 undefined behavior
                          | behavior, upon use of a nonportable or erroneous program construct
                          | or of erroneous data, for which this International Standard imposes
                          | no requirements
                          |
                          | 2 NOTE Possible undefined behavior ranges from ignoring the
                          | situation completely with unpredictable results, to behaving during
                          | translation or program execution in a documented manner
                          | characteristic of the environment (with or without the issuance of
                          | a diagnostic message), to terminating a translation or execution
                          | (with the issuance of a diagnostic message).

                          Martin


                          --
                          ,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
                          / ,- ) http://www.zero-based.org/ ((_/)o o(\_))
                          \ `-' `-'(. .)`-'
                          `-. Debian, a variant of the GNU operating system. \_/

                          Comment

                          • Chris Torek

                            #43
                            Re: pointer-in-array test

                            >Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:[color=blue][color=green]
                            >> index = (long)(p - a);[/color][/color]
                            [where "p" and "a" are pointers to compatible types]

                            In article <news:cju970hju p0l4udmtp70pegs da1uee8sh6@4ax. com>
                            Irrwahn Grausewitz <irrwahn33@free net.de> writes:[color=blue]
                            >Forget about the cast. Declare index as ptrdiff_t instead.[/color]

                            Yes.

                            Also, the Standard requires (of the programmer) that p and a both
                            "point into" the same underlying object, and the difference between
                            two such pointers is the (integral) number of objects separating
                            them. That is, if p == &a[i] (for any valid i), "p - a" must
                            produce i.

                            Compilers generally implement this internally by turning:

                            (ptr2 - ptr1)

                            into:

                            (((intptr_t)ptr 2 - (intptr_t)ptr1) / sizeof *ptr1)

                            This underlying division produces the desired integral answer, and
                            always has a remainder of zero. Years ago, gcc compiled this code
                            to ordinary signed integer division, which often became a right-shift
                            with a "remainder correction" step during optimization. I sent
                            email to RMS pointing out that the remainder was necessarily zero
                            -- so that the correction never corrected anything and was a waste
                            of CPU time -- and he added what is now, in gcc3, the "EXACT_DIV_EXPR "
                            expression-type. An "exact divide" is one whose remainder is known
                            in advance to be zero (by the rules of the source language).

                            Since gcc believes the C programmer got this right, the attempt to
                            do this:
                            [color=blue][color=green]
                            >> if ( (p-a) % ...[/color][/color]

                            is fundamentally flawed. Converting both pointers to to long --
                            or, better but C99-only, intptr_t -- will "do the right thing" on
                            ordinary byte-addressed machines, though.
                            --
                            In-Real-Life: Chris Torek, Wind River Systems
                            Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
                            email: forget about it http://web.torek.net/torek/index.html
                            Reading email is like searching for food in the garbage, thanks to spammers.

                            Comment

                            • Christian Bau

                              #44
                              Re: pointer-in-array test

                              In article <1308757.91vyhF nCu6@holzmayer. ifr.rt>,
                              Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:
                              [color=blue]
                              > Thomas Stegen wrote:
                              >[color=green]
                              > > Bernhard Holzmayer wrote:
                              > >[color=darkred]
                              > >> Sorry,
                              > >> pardon me for not checking my code intensively enough.
                              > >> I just checked with a 'gcc -pedantic' which didn't throw an error
                              > >> :(
                              > >>
                              > >> What about this solution:
                              > >> int ptrInArrSafe(T *p,T *a,int max)
                              > >> /* check whether p points to an element of a[max] */
                              > >> {
                              > >> long px = (long)p;
                              > >> long ax = (long)a;
                              > >> if (px<ax) return 0; /*out*/
                              > >> if (px> (long)&a[max-1]) return 0; /* out */
                              > >> if ( (px-ax) % sizeof(T)) return 0; /* not at element
                              > >> start*/
                              > >> return 1; /* in and on element start */
                              > >> }[/color][/color]
                              >
                              > After a close look to K&R 5.3 and additional sources, I'd like
                              > to improve the above a little.[/color]

                              Take a copy of the C Standard as an additional source.

                              [color=blue]
                              > What about the following modified
                              > version:
                              >
                              > int ptrInArrSafe(T *p,T *a,int max)
                              > /* check whether p points to an element of a[max] */
                              > {
                              > long index;
                              >
                              > /* as long as a points to a valid array, this is a legal
                              > test for the lower boundary*/
                              > if (p<a) return 0; /*out */[/color]

                              Wrong. That single comparison can invoke undefined behavior and make
                              your program crash. No need to read any further.

                              [color=blue]
                              > /* evaluation of element's address is valid for all elements
                              > including the virtual last+1 element, though its content may not be
                              > retrieved, comparison is legal test for upper boundary */
                              > if (!(p<&a[max])) return 0; /* out */
                              >
                              > /* now we can be sure that we are inside array, because
                              > standard requires that array is in a logically "dense" order, from
                              > point of logical addresses they must be accessible in ascending
                              > order */
                              >
                              > index = (long)(p - a);
                              > /* as far as I understand, it's possible that p-a returns
                              > the difference in multiples of sizeof(T), so that if element size
                              > were 2, a[2]-a[1] would give 1 instead of 2.
                              > Although I never found a compiler doing this, I replace sizeof(T) by
                              > a method which should work in both cases. */
                              > if ( (p-a) % (&a[1]-&a[0]))
                              > return 0; /* not at element boundary*/
                              >
                              > return 1; /* in and on element boundary */
                              > }
                              >
                              > Bernhard[/color]

                              Comment

                              • Christian Bau

                                #45
                                Re: pointer-in-array test

                                In article <1429677.E0U4Dc PHEJ@holzmayer. ifr.rt>,
                                Bernhard Holzmayer <holzmayer.bern hard@deadspam.c om> wrote:
                                [color=blue]
                                > pete wrote:
                                >[color=green]
                                > > Bernhard Holzmayer wrote:
                                > >[color=darkred]
                                > >> IMHO you have to use pointer-to-long which must be well-defined
                                > >> according to the standard, which means, that a long is big enough
                                > >> to hold a pointer on that system. An integer might be too short.[/color]
                                > >
                                > > Whether or not a pointer can be converted to any integer type
                                > > is implementation defined.
                                > > The standard does not guarantee that relationships which hold
                                > > for two pointers, will also hold for their converted integer
                                > > values.
                                > >
                                > > N869
                                > > 6.3.2.3 Pointers
                                > > [#6] Any pointer type may be converted to an integer
                                > > [#type.
                                > > Except as previously specified, the result
                                > > is
                                > > implementation-defined. If the result cannot be
                                > > represented
                                > > in the integer type, the behavior is undefined. The
                                > > result need not be in the range of values of any integer
                                > > type.
                                > >[/color]
                                >
                                > 1) Isn't it correct, that long has to be of the size to hold any
                                > pointer, so that a conversion:
                                > (pType *) --> (void *) ---> (long)
                                > and vice versa is legal?[/color]

                                No. It is entirely possible that there is no integer type big enough to
                                hold all possible pointer values.

                                [color=blue]
                                > 2) Isn't it correct, that arrays must have their elements arranged
                                > subsequently, so that array == &array[0] and
                                > &array[1]>&array[0] are valid?[/color]

                                True. But if you compare pointers that don't point into the same array,
                                all odds are off.

                                Comment

                                Working...