Author Topic: casting pointers?  (Read 4954 times)

0 Members and 1 Guest are viewing this topic.

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
casting pointers?
« on: March 17, 2007 »
I'm wanting to cast pointers into something else but devc pointers are 32 bit and can be cast into ints, VC pointers on the other hand are 64 bit so can't be, is there any way to make my own data type that i can cast pointers into that can be set to the sizeof pointers?

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: casting pointers?
« Reply #1 on: March 17, 2007 »
The type intptr_t is defined in the new standard, if it's not there then you just have to guess and use unsigned int.  But VC pointers aren't 64bit, so I don't know what's wrong there.

Jim

Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: casting pointers?
« Reply #2 on: March 17, 2007 »
Hmm, VC shows 4 bytes for a pointer but why am I getting truncation warnings (and errors going the other way) when i try to cast a pointer into an int and no warnings when i cast into a long long in VC, no such warnings when i do it with ints in devc?

Solved my problem by casting into int pointers for now.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: casting pointers?
« Reply #3 on: March 17, 2007 »
Use unsigned int, not int.  Visual Studio is just giving you extra warnings that you're doing something unusual.
Try doing
printf("%u\n", sizeof(void *));
on each platform.  I'm positive they'll both display 4.

Jim
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: casting pointers?
« Reply #4 on: March 17, 2007 »
Yep, both give 4. I got the same warnings with unsigned int:

pointer truncation from 'image_struct *' to 'unsigned int'

and

conversion from 'unsigned int' to 'image_struct *' of greater size



EDIT:
no warnings if i use long long.
« Last Edit: March 17, 2007 by Stonemonkey »

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: casting pointers?
« Reply #5 on: March 17, 2007 »
OK, this is because VC is 64bit ready.  It's warning you that when you port your code up to 64bit mode it might not work.
Go to
Project->Properties->Configuration Properties->C/C++->General->Detect 64-bit Portability Issues
and set it to No.

I don't get any errors using unsigned int, I just get warnings with that set to Yes. eg.
Code: [Select]
typedef struct
{
float x,y,z;
} myvec;

int main(void)
{
unsigned int p;
myvec v;
myvec *vptr;

v.x = v.y = v.z = 0;

p = (unsigned int)&v;

vptr = (myvec *)p;

return 0;
}
I get
Code: [Select]
d:\source\d3dsample\cast\cast.cpp(14) : warning C4311: 'type cast' : pointer truncation from 'myvec *__w64 ' to 'unsigned int'
d:\source\d3dsample\cast\cast.cpp(16) : warning C4312: 'type cast' : conversion from 'unsigned int' to 'myvec *' of greater size

Another possible fix is to use uintptr_t (if it's available) which is an unsigned integer type guaranteed to be big enough to hold any pointer type.  In VC uintptr_t is defined in stddef.h (it should be in stdint.h, but VC doesn't have that yet, all this stuff is too new).
Code: [Select]
#include <stddef.h>

typedef struct
{
float x,y,z;
} myvec;

int main(void)
{
uintptr_t p;
myvec v;
myvec *vptr;

v.x = v.y = v.z = 0;

p = (uintptr_t)&v;

vptr = (myvec *)p;

return 0;
}

If you dig down through the headers you can see why this works.  In 32bit mode it's unsigned int, in 64bit mode it's unsigned __int64 (which is the same as unsigned long long).

Code: [Select]
#ifdef  _WIN64
typedef unsigned __int64    uintptr_t;
#else
typedef _W64 unsigned int   uintptr_t;
#endif

The _W64 (__w64) bit is Microsoft's internal tag to control the generation of warning.

Jim
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: casting pointers?
« Reply #6 on: March 17, 2007 »
Ah right, thanks Jim. Not entirely sure where the errors were coming from, probably just messed something up while trying to figure out the warnings.

Offline Emil_halim

  • Atari ST
  • ***
  • Posts: 248
  • Karma: 21
    • View Profile
    • OgreMagic Library
Re: casting pointers?
« Reply #7 on: March 17, 2007 »
Just for  clearnce , any pointer in C++ is consistes of 4 bytes so it is the same size (in 32bits platform)  as int , unsigned int , long , and even float  type.

So what is the problem?

Actually the problem may take place when you use the pointer as an array to get what it holds, i.e dereference it.

For example

Suppose you have a pointer to int type and an other one for byte type and want to use them as an arrays to get the 4 th element from the beginning.

Code: [Select]
int    *int_ptr;    // I am integer pointer , size of integer is 4 bytes.
byte *byte_ptr; // I am byte pointer , size of byte is 1 bytes.

 int int_val =  int_ptr[3]; 
/*
C++ compiler will multiply 3 * size of int type (i.e 4 bytes) to get the address of 4 th element . i.e  address = int_ptr  + 3 * size of int type (4 bytes) = int_ptr + 12 bytes
*/

 int int_val = byte_ptr[3];
 /*
C++ compiler will multiply 3 * size of byte type (i.e 1 byte) to get the address of 4 th element . i.e  address = byte_ptr  + 3 * size of  byte type (1 byte) = byte_ptr + 3 bytes
Which is wrong address. And the compiler will fire a warning.
*/


Note well
some times you do want to get a certain byte from an integer value , so you use a byte pointer to get the desired byte but with explicitly  casting type

for example

this get the second byte from integer value ,

Code: [Select]

int  int_val ;
byte* byte_ptr =  (byte*) & int_val ;
byte mySecondByte =    byte_ptr[1];


hope that will make things more clear , and sorry for my bad English.