user2131316
user2131316

Reputation: 3287

what does the following type casting do in C?

I have a question about type casting in C:

void *buffer;

(int *)((int)buffer);

what is this type casting doing? and what does the ((int)buffer) doing?

Upvotes: 3

Views: 493

Answers (3)

Gene
Gene

Reputation: 47020

Let's see what the C Standard has to say. On page 55 of the last freely published version of the C11 standard http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf we have

5 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.

6 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.

What does this mean in your example? Section 6 says that the cast (int)buffer will compile, but if the integer is not big enough to hold the pointer (which is likely on 64-bit machines), the result is undefined. The final (int*) casts back to a pointer.

Section 5 says that if the integer was big enough to hold the intermediate result, the result is exactly the same as just casting to (int*) from the outset.

In short the cast (int) is at best useless and at worst causes the pointer value to be lost.

Upvotes: 2

Imagine you are on a Linux/x86-64 computer like mine. Then pointers are 64 bits and int is 32 bits wide.

So, the buffer variable has been initialized to some location; Perhaps 0x7fff4ec52020 (which could be the address of some local variable, perhaps inside main).

The cast (int)buffer gives you an int, probably the least significant 32 bits, i.e. 0x4ec52020

You are casting again with (int*)((int)buffer), which gives you the bogus address 0x000000004ec52020 which does not point into valid memory. If you dereference that bogus pointer, you'll very probably get a SIGSEGV.

So on some machines (notably mine) (int *)((int)buffer) is not the same as (int*)buffer;

Fortunately, as a statement, (int *)((int)buffer); has no visible side effect and will be optimized (by "removing" it) by the compiler (if you ask it to optimize).

So such code is a huge mistake (could become an undefined behavior, e.g. if you dereference that pointer). If the original coder really intended the weird semantics described here, he should add a comment (and such code is unportable)!

Perhaps #include-ing <stdint.h> and using intptr_t or uintptr_t could make more sense.

Upvotes: 5

JaredPar
JaredPar

Reputation: 755387

In straight C code this is pointless because conversions to and from void* are implicit. The following would compile just fine

int* p = buffer;

Worse though is this code potentially introduces errors. Consider the case of a 64 bit platform. The conversion to int will truncate the pointer to 32 bits and then assign it to an int*. This will cause the pointer value to be truncated and certainly lead to errors.

Upvotes: 0

Related Questions