Dark Bit Factory & Gravity
PROGRAMMING => C / C++ /C# => Topic started by: Stonemonkey 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?
-
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
-
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.
-
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
-
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.
-
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.
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
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).
#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).
#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
-
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.
-
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.
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 ,
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.