Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get "cast from pointer to integer of different size" error?

Tags:

c

pointers

gcc

The following line (pure c) compiles cleanly on windows (win7 64 bits + codeblocks 13 + mingw32) and debian (wheezy 32 bits + codeblocks 10 + gcc) but raises warning on kali (64 bits + codeblocks + gcc). Any comments? I mean, why do I get this warning, though the same line compiles w/o any warning on windows & debian?

void* foo(void *dst, ...) {
    // some code
    unsigned int blkLen = sizeof(int); // this line ok.
    unsigned int offset = (unsigned int) dst % blkLen; // warning here!
    // some code cont...
}

The message in codeblocks is: "error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]"

note: my compiler options are -std=c99 -Werror -save-temps (same on all three systems).

edit 2: Though I've managed to have it compiled w/o warning using the preprocessor lines below, @Keith Thompson (see below) has a crucial point about the issue. So, my last decision is using uintptr_t would be a better choice.

edit 1: Thanks for everyone replied. As all the replies note, the problem is a 32 bits vs 64 bits issue. I've inserted following preprocessor lines:

#if __linux__   //  or #if __GNUC__
    #if __x86_64__ || __ppc64__
        #define ENVIRONMENT64
    #else
        #define ENVIRONMENT32
    #endif
#else
    #if _WIN32
        #define ENVIRONMENT32
    #else
        #define ENVIRONMENT64
    #endif
#endif // __linux__

#ifdef ENVIRONMENT64
    #define MAX_BLOCK_SIZE unsigned long long int
#else
    #define MAX_BLOCK_SIZE unsigned long int
#endif // ENVIRONMENT64

and then replaced the problem line as:

unsigned int offset = (MAX_BLOCK_SIZE) dst % blkLen;

Now, everything seems OK.

like image 583
ssd Avatar asked Nov 07 '14 16:11

ssd


People also ask

What happens when you cast a pointer to an int?

Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

Can you typecast pointer from void to int?

You're return ing the value of int sum by setting a void * address to it. In this case, the address is not valid. But, if you keep that in mind and get the value of sum by casting a void * to int it will work.

Can you cast a pointer?

Casting a pointer to a different pointer and back is usually safe and yields the original value. The limitations are that object pointers can be cast only to object pointers with similar or stricter alignment requirements, and function pointers can be cast only to function pointers.

Which type of cast allows the conversion of pointers of one type to pointers of another type even if the classes are unrelated?

reinterpret_cast converts any pointer type to any other pointer type, even of unrelated classes. The operation result is a simple binary copy of the value from one pointer to the other.


1 Answers

The reason for the warning is that the compiler suspects you might be trying to round-trip a pointer through int and back. This was common practice before the advent of 64-bit machines and it is not safe or reasonable. Of course here the compiler can clearly see that you're not doing this, and it would be nice if it were smart enough to avoid the warning in cases like this, but it's not.

A clean alternative that avoids the warning, and another much nastier issue of wrong result when the converted value is negative, is:

unsigned int offset = (uintptr_t) dst % blkLen;

You'll need to include stdint.h or inttypes.h to have uintptr_t available.

like image 104
R.. GitHub STOP HELPING ICE Avatar answered Oct 04 '22 06:10

R.. GitHub STOP HELPING ICE