473,406 Members | 2,345 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

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 1822
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

22
by: lokman | last post by:
Hi, In the following code, can someone tell me the difference between *p++ and p++ ? I can see both achieve the same result. Thanks a lot !
21
by: MOvetsky | last post by:
Is the following code ISO C++ standard compliant? If yes, is it guaranteed that it will not crash on compliant platforms? If yes, will it print "Pointers are equal" on any compliant platform? Will...
204
by: Alexei A. Frounze | last post by:
Hi all, I have a question regarding the gcc behavior (gcc version 3.3.4). On the following test program it emits a warning: #include <stdio.h> int aInt2 = {0,1,2,4,9,16}; int aInt3 =...
51
by: Kuku | last post by:
What is the difference between a reference and a pointer?
14
by: shaanxxx | last post by:
int main() { int *i = (int *) &i; } Above statement is a valid statement as per standard ? Since object is getting created and same time i am trying to store its address in itself, it is...
11
by: quakewang | last post by:
hi, I have define in a head file like this: #define GLUT_BITMAP_9_BY_15 ((void*)2) #define GLUT_BITMAP_8_BY_13 ((void*)3) #define GLUT_BITMAP_TIMES_ROMAN_10 ...
7
by: Pietro Cerutti | last post by:
Hi group. I have a problem in a program structured like this: void function_1(my_data_t *data); my_data_t *create_data(void); void library_function(void); int main(void) { my_data_t *data;
49
by: Davy | last post by:
Hi all, I am writing a function, which return the pointer of the int. But it seems to be wrong. Any suggestion? int * get_p_t(int t) { return &t; } int main()
3
by: tfelb | last post by:
Hi group! I have here five different declarations but I have some problems to understand this concept. I know there are more examples if I would use parentheses but I think the following ones...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.