Connecting Tech Pros Worldwide Forums | Help | Site Map

Pointer decrementation delivers wrong result

Hipo
Guest
 
Posts: n/a
#1: May 31 '06
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

Rolf Magnus
Guest
 
Posts: n/a
#2: May 31 '06

re: Pointer decrementation delivers wrong result


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

&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 &).
[color=blue]
> 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.[/color]

Hipo
Guest
 
Posts: n/a
#3: May 31 '06

re: Pointer decrementation delivers wrong result


Rolf Magnus schrieb:[color=blue]
> Hipo wrote:
>[color=green]
>> Hi.
>>
>> I have the following code:
>>
>> unsigned char temporary[160];
>> unsigned __int64 *reader = (unsigned __int64*)&temporary+20;[/color]
>
> &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 &).[/color]

Sorry, typing error
[color=blue][color=green]
>> 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.[/color]
>[/color]

g, Hipo
Greg
Guest
 
Posts: n/a
#4: May 31 '06

re: Pointer decrementation delivers wrong result


Rolf Magnus wrote:[color=blue]
> Hipo wrote:
>[color=green]
> > Hi.
> >
> > I have the following code:
> >
> > unsigned char temporary[160];
> > unsigned __int64 *reader = (unsigned __int64*)&temporary+20;[/color]
>
> &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 &).[/color]

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

Rolf Magnus
Guest
 
Posts: n/a
#5: May 31 '06

re: Pointer decrementation delivers wrong result


Greg wrote:
[color=blue]
> Rolf Magnus wrote:[color=green]
>> Hipo wrote:
>>[color=darkred]
>> > Hi.
>> >
>> > I have the following code:
>> >
>> > unsigned char temporary[160];
>> > unsigned __int64 *reader = (unsigned __int64*)&temporary+20;[/color]
>>
>> &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 &).[/color]
>
> Eliminating the & in front of the temporary array makes no difference -
> the address of the reader variable is the same.[/color]

Oh. right. The pointer gets converted first, then the addidtion is done. I
was thinking the other way round.

boaz_sade@yahoo.com
Guest
 
Posts: n/a
#6: May 31 '06

re: Pointer decrementation delivers wrong result



Greg wrote:[color=blue]
> Rolf Magnus wrote:[color=green]
> > Hipo wrote:
> >[color=darkred]
> > > Hi.
> > >
> > > I have the following code:
> > >
> > > unsigned char temporary[160];
> > > unsigned __int64 *reader = (unsigned __int64*)&temporary+20;[/color]
> >
> > &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 &).[/color]
>
> 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[/color]
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?

Tomás
Guest
 
Posts: n/a
#7: May 31 '06

re: Pointer decrementation delivers wrong result


Greg posted:

[color=blue]
> This code certainly makes a good example why pointers and C arrays are
> best avoided.[/color]



Unless of course the programmer is competent.


-Tomás
Tomás
Guest
 
Posts: n/a
#8: May 31 '06

re: Pointer decrementation delivers wrong result


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


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])

);

[color=blue]
> std::cout << *reader-- << std::endl;
> std::cout << *reader-- << std::endl;
> std::cout << *reader-- << std::endl;[/color]


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
Hipo
Guest
 
Posts: n/a
#9: May 31 '06

re: Pointer decrementation delivers wrong result


boaz_sade@yahoo.com schrieb:[color=blue]
> Greg wrote:[color=green]
>> Rolf Magnus wrote:[color=darkred]
>>> 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 &).[/color]
>> 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[/color]
> I think that this is an example of how you can violatate and rule about
> writing good code.[/color]

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

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

Believe me, I do.
[color=blue]
> Last and not least why on earth would you ever even think about writing
> this kind of code?[/color]

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

g, hipo
Hipo
Guest
 
Posts: n/a
#10: May 31 '06

re: Pointer decrementation delivers wrong result


Tomás schrieb:[color=blue]
> Hipo posted:
>[color=green]
>> Hi.
>>
>> I have the following code:
>>
>> unsigned char temporary[160];[/color]
>[color=green]
>> unsigned __int64 *reader = (unsigned __int64*)&temporary+20;[/color]
>
>
> 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])
>
> );
>
>[color=green]
>> std::cout << *reader-- << std::endl;
>> std::cout << *reader-- << std::endl;
>> std::cout << *reader-- << std::endl;[/color]
>
>
> 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[/color]

Thanks for advice, I'll trying it this way.
g, Hipo
Joe Van Dyk
Guest
 
Posts: n/a
#11: May 31 '06

re: Pointer decrementation delivers wrong result


Hipo wrote:[color=blue]
> boaz_sade@yahoo.com schrieb:
>[color=green]
>> Greg wrote:
>>[color=darkred]
>>> 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[/color]
>>
>> I think that this is an example of how you can violatate and rule about
>> writing good code.[/color]
>
>
> Define good code. I need the data that way and therefor work on it that
> way.
>[color=green]
>> Above all this is not even deterministic on different compilers.[/color]
>
>
> Not desired. One specific compiler on one specific platform.
>[color=green]
>> Even better it seems that the write of this code don't know how should
>> it really works.[/color]
>
>
> Believe me, I do.
>[color=green]
>> Last and not least why on earth would you ever even think about writing[/color]
>[color=green]
> > this kind of code?[/color]
>
> It's the most efficient way of using data in the algorithm I write.
>
> g, hipo[/color]

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

Joe
Ron House
Guest
 
Posts: n/a
#12: Jun 1 '06

re: Pointer decrementation delivers wrong result


Greg wrote:[color=blue]
> Rolf Magnus wrote:
>[color=green]
>>Hipo wrote:
>>
>>[color=darkred]
>>>Hi.
>>>
>>>I have the following code:
>>>
>>>unsigned char temporary[160];
>>>unsigned __int64 *reader = (unsigned __int64*)&temporary+20;[/color]
>>
>>&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 &).[/color]
>
>
> 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.[/color]

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 house@usq.edu.au
http://www.sci.usq.edu.au/staff/house
Closed Thread


Similar C / C++ bytes