pointer truncation from 'void *' to 'int'

C

CBFalconer

Keith said:
No, a pointer is not necessarily an integer address of a memory
cell. It is on many systems, but the standard makes no such
guarantee, and there are real-world systems where the assumption
breaks down.

I have watched this silly "discussion" go on for two days, or so,
an nobody seems to want to bother to tell the poor OP that he
failed to #include <stdlib.h>.
 
A

Alfonso Morra

Barry said:
Converting from void* to datatype* does not involve any integer
conversion. Furthermore, a cast is not necessary. Your assumption
about the cause of the error message is suspect.




While the representation of a pointer value may coincide with the
representation of an integer value, the two types are completely
distinct. Pointers are stored in objects with type pointer to T and
integers are stored in objects with type int (or long or short, etc).




If there was nothing to worry about, the compiler would probably not
be bringing it to your attention (though not universally true). In
this case, it definitely is something to worry about.




Probably not relevant.




You apparently did something unintended. Show us your code.

Here is a snippet of one of the functions that causes the compiler to
barf (note the language is C++), but I'm not really doing anything C++
specific :


void *SharedMemory::Create(int memsize) {
SharedMemory::HEADER *p = NULL;

/* Code to alloc mem etc */
....
p = (SharedMemory::HEADER *) ((int)p + p->size); //offending line
....
}
 
R

Richard Bos

Alfonso Morra said:
Here is a snippet of one of the functions that causes the compiler to
barf (note the language is C++), but I'm not really doing anything C++
specific :

Yes, you are. First of all, you're asking about void *s, which behave
differently in C and in C++; C++ sacrificed some usefulness for
theoretical (but not practical) type-safety. Second:
void *SharedMemory::Create(int memsize) {
^^
SharedMemory::HEADER *p = NULL;
^^
p = (SharedMemory::HEADER *) ((int)p + p->size); //offending line
^^
Richard
 
G

Grumble

Charles said:
Altough the C standard doesn't say so, *most* (99.9%) of C
implementations have sizeof(long)==sizeof(void *), so you
can convert pointer to long and back again.

Not really. MSVC on AMD64 has, AFAICT,
CHAR_BIT == 8
sizeof(long) == 4
sizeof(void *) == 8

http://www.microsoft.com/whdc/winhec/partners/64bitAMD.mspx

<quote>
Another bad bit of code casts a pointer to a long. Such code would run
properly on 32-bit Windows, but the pointer will get truncated when you
compile the code for 64-bit Windows.
</quote>

Do you claim the market share of Visual Studio on AMD64/EM64T is
less than 0.1 percent?
 
R

Richard Bos

Grumble said:
Not really. MSVC on AMD64 has, AFAICT,
CHAR_BIT == 8
sizeof(long) == 4
sizeof(void *) == 8

http://www.microsoft.com/whdc/winhec/partners/64bitAMD.mspx

<quote>
Another bad bit of code casts a pointer to a long. Such code would run
properly on 32-bit Windows, but the pointer will get truncated when you
compile the code for 64-bit Windows.
</quote>

Guess where such behaviour is rife, and can hardly be avoided? Right,
the Windows API. Grumble.

Richard
 
E

Eric Sosman

Alfonso said:
Here is a snippet of one of the functions that causes the compiler to
barf (note the language is C++), but I'm not really doing anything C++
specific :

Well, there's some dodgy syntax.
void *SharedMemory::Create(int memsize) {
SharedMemory::HEADER *p = NULL;

/* Code to alloc mem etc */
...
p = (SharedMemory::HEADER *) ((int)p + p->size); //offending line

Yes, that line offends. Not only is it offensive, but
it's dumb. Why rely on an unreliable implementation-defined
non-portable conversion when there's a reliable well-defined
fully portable alternative?

p = (SharedMemory::HEADER*) ((char*)p + p->size);

Shoving pointy sticks up my nose improves my disposition,
because it feels *so* good when I stop.
 
S

Steve Summit

Alfonso said:
Here is a snippet of one of the functions that causes the compiler to
barf (note the language is C++), but I'm not really doing anything C++
specific :

As Richard has already pointed out, those :: namespace operators
indicate that you certainly *are* doing something C++ specific!
SharedMemory::HEADER *p = NULL;
/* Code to alloc mem etc */
p = (SharedMemory::HEADER *) ((int)p + p->size); //offending line

What in the world are you trying to do here?! You're taking a
null pointer, casting it to an int, adding (I presume) another
int to it, and then trying to cast the result back to a pointer.
Moreover, unless I'm missing something, the int you're adding in
(that is, p->size) is fetched off of the null pointer you started
with. This doesn't look like it'll do anything useful, and it
*certainly* doesn't look like it'll allocate any memory!

I'm not sure I would have expected the compiler's first complaint
here to be about truncation of void * to int (in particular,
there aren't any void pointers in sight), but I'm glad it
complained about something, because you definitely need to
reexamine your thinking.

(There's an old rule, and it certainly applies here, that casts
should be used sparingly, and only when you know what you're
doing, and certainly not willy-nilly just to shut the compiler
up. In particular, you don't allocate memory by casting an int
to a pointer; you've got to call a memory-allocation function
somewhere! When the compiler complains about attempted
int-to-pointer conversions, and unless you're writing low-level
pointer manipulation code of the sort that only a linker ought to
be doing, the complaint almost invariably indicates that you're
mixing apples and oranges in an irreconciliable way, which the
insertion of a bunch of casts will only make worse.)

If the comment "Code to alloc mem etc" replaces some explicit
memory-allocation logic that is in your actual code; if p has
been appropriately set up to point at a SharedMemory::HEADER
object by the time you hit the line

p = (SharedMemory::HEADER *) ((int)p + p->size);

the problem may simply be that (int) cast, which is truncating a
pointer into an int (though the pointer it's truncating is a
SharedMemory::HEADER *, not a void *). What happens if you
remove both casts? That is, what happens if you use the
straightforward

p = p + p->size;

instead? That's normal-looking pointer arithmetic, and is
probably closer to what you want. The explicit casts make me
suspect that at some point you were either (a) trying to do the
pointer arithmetic in chunks of other than sizeof(SharedMemory::HEADER),
or (b) using void pointers which the compiler (correctly) wouldn't
let you do arithmetic on at all.

Steve Summit
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top