470,841 Members | 1,118 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,841 developers. It's quick & easy.

Pointer decrementation delivers wrong result

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
May 31 '06 #1
11 1713
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.


May 31 '06 #2
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
May 31 '06 #3
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

May 31 '06 #4
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.

May 31 '06 #5

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 '06 #6
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
May 31 '06 #7
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
May 31 '06 #8
bo*******@yahoo.com 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
May 31 '06 #9
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
May 31 '06 #10
Hipo wrote:
bo*******@yahoo.com 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
May 31 '06 #11
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 ho***@usq.edu.au
http://www.sci.usq.edu.au/staff/house
Jun 1 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

22 posts views Thread by lokman | last post: by
21 posts views Thread by MOvetsky | last post: by
204 posts views Thread by Alexei A. Frounze | last post: by
51 posts views Thread by Kuku | last post: by
14 posts views Thread by shaanxxx | last post: by
11 posts views Thread by quakewang | last post: by
7 posts views Thread by Pietro Cerutti | last post: by
49 posts views Thread by Davy | last post: by
3 posts views Thread by tfelb | last post: by
reply views Thread by mihailmihai484 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.