Pointer decrementation delivers wrong result

Discussion in 'C++' started by Hipo, May 31, 2006.

  1. Hipo

    Hipo Guest

    Hi.

    I have the following code:

    unsigned char temporary[160];
    unsigned __int64 *reader = (unsigned __int64*)&temporary+20;

    std::cout << *reader-- << std::endl;
    std::cout << *reader-- << std::endl;
    std::cout << *reader-- << std::endl;



    The first output and the third output are OK. But the second output
    gives me data that doesn't match to any values in the char array.
    If I'm doing the same operation from the beginning and incrementing the
    pointer all values are read like they should.

    I'm really puzzled.

    g, Hipo
    Hipo, May 31, 2006
    #1
    1. Advertising

  2. Hipo

    Rolf Magnus Guest

    Hipo wrote:

    > Hi.
    >
    > I have the following code:
    >
    > unsigned char temporary[160];
    > unsigned __int64 *reader = (unsigned __int64*)&temporary+20;


    &temporary is the address of the array. &temporary+20 would be the address
    of the 20th element of an array of arrays of 160 char. You probably meant
    temporary+20 (without the &).

    > std::cout << *reader-- << std::endl;
    > std::cout << *reader-- << std::endl;
    > std::cout << *reader-- << std::endl;
    >
    >
    >
    > The first output and the third output are OK. But the second output
    > gives me data that doesn't match to any values in the char array.
    > If I'm doing the same operation from the beginning and incrementing the
    > pointer all values are read like they should.
    Rolf Magnus, May 31, 2006
    #2
    1. Advertising

  3. Hipo

    Hipo Guest

    Rolf Magnus schrieb:
    > Hipo wrote:
    >
    >> Hi.
    >>
    >> I have the following code:
    >>
    >> unsigned char temporary[160];
    >> unsigned __int64 *reader = (unsigned __int64*)&temporary+20;

    >
    > &temporary is the address of the array. &temporary+20 would be the address
    > of the 20th element of an array of arrays of 160 char. You probably meant
    > temporary+20 (without the &).


    Sorry, typing error

    >> std::cout << *reader-- << std::endl;
    >> std::cout << *reader-- << std::endl;
    >> std::cout << *reader-- << std::endl;
    >>
    >>
    >>
    >> The first output and the third output are OK. But the second output
    >> gives me data that doesn't match to any values in the char array.
    >> If I'm doing the same operation from the beginning and incrementing the
    >> pointer all values are read like they should.

    >


    g, Hipo
    Hipo, May 31, 2006
    #3
  4. Hipo

    Greg Guest

    Rolf Magnus wrote:
    > Hipo wrote:
    >
    > > Hi.
    > >
    > > I have the following code:
    > >
    > > unsigned char temporary[160];
    > > unsigned __int64 *reader = (unsigned __int64*)&temporary+20;

    >
    > &temporary is the address of the array. &temporary+20 would be the address
    > of the 20th element of an array of arrays of 160 char. You probably meant
    > temporary+20 (without the &).


    Eliminating the & in front of the temporary array makes no difference -
    the address of the reader variable is the same. And that address works
    out to the 21st element of an array of 8 byte integers which in turn is
    equivalent to the address of the 161st character of the 160 character
    array. In other words, the reader variable starts by pointing to the
    first byte beyond the memory allocated for the temporary array.

    This code certainly makes a good example why pointers and C arrays are
    best avoided.

    Greg
    Greg, May 31, 2006
    #4
  5. Hipo

    Rolf Magnus Guest

    Greg wrote:

    > Rolf Magnus wrote:
    >> Hipo wrote:
    >>
    >> > Hi.
    >> >
    >> > I have the following code:
    >> >
    >> > unsigned char temporary[160];
    >> > unsigned __int64 *reader = (unsigned __int64*)&temporary+20;

    >>
    >> &temporary is the address of the array. &temporary+20 would be the
    >> address of the 20th element of an array of arrays of 160 char. You
    >> probably meant temporary+20 (without the &).

    >
    > Eliminating the & in front of the temporary array makes no difference -
    > the address of the reader variable is the same.


    Oh. right. The pointer gets converted first, then the addidtion is done. I
    was thinking the other way round.
    Rolf Magnus, May 31, 2006
    #5
  6. Hipo

    Guest

    Greg wrote:
    > Rolf Magnus wrote:
    > > Hipo wrote:
    > >
    > > > Hi.
    > > >
    > > > I have the following code:
    > > >
    > > > unsigned char temporary[160];
    > > > unsigned __int64 *reader = (unsigned __int64*)&temporary+20;

    > >
    > > &temporary is the address of the array. &temporary+20 would be the address
    > > of the 20th element of an array of arrays of 160 char. You probably meant
    > > temporary+20 (without the &).

    >
    > Eliminating the & in front of the temporary array makes no difference -
    > the address of the reader variable is the same. And that address works
    > out to the 21st element of an array of 8 byte integers which in turn is
    > equivalent to the address of the 161st character of the 160 character
    > array. In other words, the reader variable starts by pointing to the
    > first byte beyond the memory allocated for the temporary array.
    >
    > This code certainly makes a good example why pointers and C arrays are
    > best avoided.
    >
    > Greg

    I think that this is an example of how you can violatate and rule about
    writing good code. Above all this is not even deterministic on
    different compilers. Even better it seems that the write of this code
    don't know how should it really works. Last and not least why on earth
    would you ever even think about writing this kind of code?
    , May 31, 2006
    #6
  7. Hipo

    Tomás Guest

    Greg posted:


    > This code certainly makes a good example why pointers and C arrays are
    > best avoided.




    Unless of course the programmer is competent.


    -Tomás
    Tomás, May 31, 2006
    #7
  8. Hipo

    Tomás Guest

    Hipo posted:

    > Hi.
    >
    > I have the following code:
    >
    > unsigned char temporary[160];


    > unsigned __int64 *reader = (unsigned __int64*)&temporary+20;



    That line behaves identically to:


    unsigned __int64 *reader = reinterpret_cast<unsigned __int64 *>(

    reinterpret_cast<char *>(temporary) + sizeof(unsigned __int64[20])

    );



    "reader" now points to the first byte AFTER the last element of
    "temporary". Try changing that 20 to 12:


    unsigned __int64 *reader = reinterpret_cast<unsigned __int64 *>(

    reinterpret_cast<char *>(temporary) + sizeof(unsigned __int64[12])

    );


    > std::cout << *reader-- << std::endl;
    > std::cout << *reader-- << std::endl;
    > std::cout << *reader-- << std::endl;



    Two caveats:

    (1) Beware of trapping bits.
    (2) You're deallocating the pointer to one BEFORE the array.


    Try the following code:

    #include <iostream>
    #include <ostream>
    #include <cstdlib>

    enum { quantity = 20 };

    int main()
    {
    typedef unsigned __int64 uint64;

    uint64 big_numbers[quantity] =
    { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,
    11,12,13,14,15,16,17,18,19,20 };

    unsigned char temporary[160];


    /* That would be better written as:

    unsigned char temporary[ sizeof(uint64[quantity]) ]; */


    std::memcpy(temporary, big_numbers, sizeof( big_numbers ) );


    for(uint64 *reader = reinterpret_cast<uint64*>(

    reinterpret_cast<char *>(temporary)
    + sizeof(uint64[20])

    );

    reader-- > reinterpret_cast<uint64*>(temporary);

    /* No action */ )
    {
    std::cout << *reader << '\n';
    }


    std::system("PAUSE");
    }



    -Tomás
    Tomás, May 31, 2006
    #8
  9. Hipo

    Hipo Guest

    schrieb:
    > Greg wrote:
    >> Rolf Magnus wrote:
    >>> Hipo wrote:
    >>>
    >>>> Hi.
    >>>>
    >>>> I have the following code:
    >>>>
    >>>> unsigned char temporary[160];
    >>>> unsigned __int64 *reader = (unsigned __int64*)&temporary+20;
    >>> &temporary is the address of the array. &temporary+20 would be the address
    >>> of the 20th element of an array of arrays of 160 char. You probably meant
    >>> temporary+20 (without the &).

    >> Eliminating the & in front of the temporary array makes no difference -
    >> the address of the reader variable is the same. And that address works
    >> out to the 21st element of an array of 8 byte integers which in turn is
    >> equivalent to the address of the 161st character of the 160 character
    >> array. In other words, the reader variable starts by pointing to the
    >> first byte beyond the memory allocated for the temporary array.
    >>
    >> This code certainly makes a good example why pointers and C arrays are
    >> best avoided.
    >>
    >> Greg

    > I think that this is an example of how you can violatate and rule about
    > writing good code.


    Define good code. I need the data that way and therefor work on it that way.

    >Above all this is not even deterministic on different compilers.


    Not desired. One specific compiler on one specific platform.

    >Even better it seems that the write of this code don't know how should it
    >really works.


    Believe me, I do.

    > Last and not least why on earth would you ever even think about writing
    > this kind of code?


    It's the most efficient way of using data in the algorithm I write.

    g, hipo
    Hipo, May 31, 2006
    #9
  10. Hipo

    Hipo Guest

    Tomás schrieb:
    > Hipo posted:
    >
    >> Hi.
    >>
    >> I have the following code:
    >>
    >> unsigned char temporary[160];

    >
    >> unsigned __int64 *reader = (unsigned __int64*)&temporary+20;

    >
    >
    > That line behaves identically to:
    >
    >
    > unsigned __int64 *reader = reinterpret_cast<unsigned __int64 *>(
    >
    > reinterpret_cast<char *>(temporary) + sizeof(unsigned __int64[20])
    >
    > );
    >
    >
    >
    > "reader" now points to the first byte AFTER the last element of
    > "temporary". Try changing that 20 to 12:
    >
    >
    > unsigned __int64 *reader = reinterpret_cast<unsigned __int64 *>(
    >
    > reinterpret_cast<char *>(temporary) + sizeof(unsigned __int64[12])
    >
    > );
    >
    >
    >> std::cout << *reader-- << std::endl;
    >> std::cout << *reader-- << std::endl;
    >> std::cout << *reader-- << std::endl;

    >
    >
    > Two caveats:
    >
    > (1) Beware of trapping bits.
    > (2) You're deallocating the pointer to one BEFORE the array.
    >
    >
    > Try the following code:
    >
    > #include <iostream>
    > #include <ostream>
    > #include <cstdlib>
    >
    > enum { quantity = 20 };
    >
    > int main()
    > {
    > typedef unsigned __int64 uint64;
    >
    > uint64 big_numbers[quantity] =
    > { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,
    > 11,12,13,14,15,16,17,18,19,20 };
    >
    > unsigned char temporary[160];
    >
    >
    > /* That would be better written as:
    >
    > unsigned char temporary[ sizeof(uint64[quantity]) ]; */
    >
    >
    > std::memcpy(temporary, big_numbers, sizeof( big_numbers ) );
    >
    >
    > for(uint64 *reader = reinterpret_cast<uint64*>(
    >
    > reinterpret_cast<char *>(temporary)
    > + sizeof(uint64[20])
    >
    > );
    >
    > reader-- > reinterpret_cast<uint64*>(temporary);
    >
    > /* No action */ )
    > {
    > std::cout << *reader << '\n';
    > }
    >
    >
    > std::system("PAUSE");
    > }
    >
    >
    >
    > -Tomás


    Thanks for advice, I'll trying it this way.
    g, Hipo
    Hipo, May 31, 2006
    #10
  11. Hipo

    Joe Van Dyk Guest

    Hipo wrote:
    > schrieb:
    >
    >> Greg wrote:
    >>
    >>> Rolf Magnus wrote:
    >>>
    >>>> Hipo wrote:
    >>>>
    >>>>> Hi.
    >>>>>
    >>>>> I have the following code:
    >>>>>
    >>>>> unsigned char temporary[160];
    >>>>> unsigned __int64 *reader = (unsigned __int64*)&temporary+20;
    >>>>
    >>>> &temporary is the address of the array. &temporary+20 would be the
    >>>> address
    >>>> of the 20th element of an array of arrays of 160 char. You probably
    >>>> meant
    >>>> temporary+20 (without the &).
    >>>
    >>> Eliminating the & in front of the temporary array makes no difference -
    >>> the address of the reader variable is the same. And that address works
    >>> out to the 21st element of an array of 8 byte integers which in turn is
    >>> equivalent to the address of the 161st character of the 160 character
    >>> array. In other words, the reader variable starts by pointing to the
    >>> first byte beyond the memory allocated for the temporary array.
    >>>
    >>> This code certainly makes a good example why pointers and C arrays are
    >>> best avoided.
    >>>
    >>> Greg

    >>
    >> I think that this is an example of how you can violatate and rule about
    >> writing good code.

    >
    >
    > Define good code. I need the data that way and therefor work on it that
    > way.
    >
    >> Above all this is not even deterministic on different compilers.

    >
    >
    > Not desired. One specific compiler on one specific platform.
    >
    >> Even better it seems that the write of this code don't know how should
    >> it really works.

    >
    >
    > Believe me, I do.
    >
    >> Last and not least why on earth would you ever even think about writing

    >
    > > this kind of code?

    >
    > It's the most efficient way of using data in the algorithm I write.
    >
    > g, hipo


    Are you sure it's the most efficient way of using data? Have you measured?

    Joe
    Joe Van Dyk, May 31, 2006
    #11
  12. Hipo

    Ron House Guest

    Greg wrote:
    > Rolf Magnus wrote:
    >
    >>Hipo wrote:
    >>
    >>
    >>>Hi.
    >>>
    >>>I have the following code:
    >>>
    >>>unsigned char temporary[160];
    >>>unsigned __int64 *reader = (unsigned __int64*)&temporary+20;

    >>
    >>&temporary is the address of the array. &temporary+20 would be the address
    >>of the 20th element of an array of arrays of 160 char. You probably meant
    >>temporary+20 (without the &).

    >
    >
    > Eliminating the & in front of the temporary array makes no difference -
    > the address of the reader variable is the same. And that address works
    > out to the 21st element of an array of 8 byte integers which in turn is
    > equivalent to the address of the 161st character of the 160 character
    > array. In other words, the reader variable starts by pointing to the
    > first byte beyond the memory allocated for the temporary array.


    Cast has higher priority than addition, so your expression:

    (unsigned __int64*)temporary+20

    means "Convert temporary to unsigned __int64*, then index 20 unsigned
    __int64's further along." And that is exactly what you tell us happened.
    I don't see the error.

    --
    Ron House
    http://www.sci.usq.edu.au/staff/house
    Ron House, Jun 1, 2006
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. melledge
    Replies:
    0
    Views:
    362
    melledge
    Jul 21, 2005
  2. robert
    Replies:
    2
    Views:
    2,467
  3. JTP PR
    Replies:
    0
    Views:
    394
    JTP PR
    Sep 26, 2009
  4. Axel Rau
    Replies:
    1
    Views:
    390
    Axel Rau
    Apr 12, 2011
  5. Michael Tan
    Replies:
    32
    Views:
    937
    Ara.T.Howard
    Jul 21, 2005
Loading...

Share This Page