简体   繁体   中英

Why casting short to void * get a warning, and from int it's okey?

See I'm using glib, and gpointer is a typedef of void *. (glib did this type to make things clear, I guess).

when I make a signal connect, I have to pass the data as void pointer (void *).

so the code is (something like this) :

...
g_signal_connect (object, function, (gpointer) data);
...

If I use short as data type, I get a warning message of gcc like this:

warning: cast to pointer from integer of different size

If I use int as data type, I get no warnings.

But in both cases, everything works well, so, why I get this warning using short?

On a 32 bit architecture, a pointer is 32 bits. An int is usually 32 bits as well - so the conversion is '1 to 1'. A short is usually 2 bytes, so casting a short to a pointer isn't normally a very safe things to do - which is why the compiler warns you.

Gcc is telling you that you cast an integer of different size to a pointer, which is dangerous mainly the other way you have it (eg. from a larger datatype to a smaller one). To silence the warning, you can use intptr_t as an intermediate type.

g_signal_connect (object, function, (gpointer)(intptr_t) data);

A short is 2 Bytes a pointer is platform dependant but usually 4 or 8 Bytes. That should be why you get that error. You probably want to pass a the reference of the short in which would be:

(gpointer) &data);

Integer to pointer conversions are implementation-dependent in C. From the ISO standard:

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

As a short (ie signed short) is usually 16 bits, and a void * pointer is usually 32 bits on 32 bit architectures or 64 bits on 64 bit architectures, GCC has to decide how to pad the extra bits. What GCC actually does is sign-extend the short, ie it copies bits 14-bit 0 into bits 14-bit 0 of the pointer, and it copies bit 15 of the short into the remaining upper bits (bits 31-15 of a 32-bit pointer, or bits 63-15 of a 64-bit pointer.) Sign-extension preserves the value if the pointer is later converted back into an integer type of different width.

short s = -1; // i.e. -> 0xffff
void *p = (void *)s; // on 32 bit system -> 0xffffffff

If sign-extension wasn't what you wanted, perhaps you just wanted a direct copy of the short into bits 15-0 of the pointer. In that case, you'd do something like this:

short s = -1; // i.e. -> 0xffff
void *p = (void *)((unsigned short)s); // on 32 bit system -> 0x0000ffff

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM