Archived

This topic is now archived and is closed to further replies.

TheToiletDuck

casting

Recommended Posts

I am having a problem with void pointers. I''m using straight C, not C++. So, I''ve got my void pointer, and I''ve malloc''d enough memory to hold a float: void *ptr; ptr = malloc(sizeof(float)); now, I want to assign a floating point value to this ptr = 17.65f; This won''t work. *ptr = 17.65f; Neither will this. *(float *)ptr = 17.65f; This seems to be the solution, although I can''t understand why, when this is legal, assuming a couple of other declarations and a good call to fopen(). int myints[10]; fread(myints, sizeof(int)*10, 1, somefile); Now, why no casting with fread()? Is there any other strange legailties with casting like this? such as: float *flptr; flptr = (float *)malloc(sizeof(float)); fread(flptr, sizeof(float), 1, somefile); Do I need a cast then? Learning all these cases is driving me round the bend, can someone shed some light on it, or point me in the direction of a good link? Any help appreciated.

Share this post


Link to post
Share on other sites

I''m only a beginner, but I think it''s to do with whether the compiler knows the size of the data pointed too.

i.e, if you do this...

LPVOID lpVoid = malloc(sizeof(float)*10);

... then when you assign a float to some of this data, the compiler doesn''t know the size of the array elements.

Alternatively, if you create a temorary pointer to a float, it can be filled in and then cast to lpvoid.

i.e.

float* lpFloat = (float*) malloc(sizeof(float*10));
*lpFloat = 3.142f;
LPVOID lpVoid = (LPVOID) lpFloat;

I hope I was of some help...

Jon.

Share this post


Link to post
Share on other sites
Here is how I would do it if I had to and according to the books I read, it''s supposed to work. I''ll explain after...

(float)(*ptr) = 17.65f;

The reasons for this is because you actually want to typecat the pointer and not just the variable ptr. As I said, this is what was in my books. Didn''t test it myself but as far as I can tell, it looks logical. It works the same way as typecasting a pointer to function... Hope this works...





Cyberdrek
Headhunter Soft
DLC Multimedia

Share this post


Link to post
Share on other sites
Actually, I''m pretty sure that "(float)(*ptr) = 17.65f;" won''t work. I see two problems.

First, if ptr is of type (void*) then there is no way to deref it, since the compiler doesn''t know how big the data pointed to is (as j0n3z mentioned).

Second, even if you change ptr to a know type such as (char*), the left side of the equation doesn''t evaluate to an l-value. By this I mean that "(float)(*ptr)" doesn''t evaluate to a valid variable. The compiler is trying to deref ptr to get a char value (into a register or whatever) and then convert that value into a float. So far no problem. Then it wants to store into that value, but it''s not a variable, it''s just a value in a register.

On the other hand, when you do "*(float*)ptr", then your telling the compiler to take the address in the variable ptr, assume that it points to a float, and then use the float that it points to. Since this evaluates to an object (a spot in memory) instead of just a casted value, it''ll work just fine.

Hope this helps.
...Syzygy

Share this post


Link to post
Share on other sites
I think what you really need to do is develop an understanding for what type-casting really does, and then you''ll be able to work out any problems you have yourself.

In your first example you have:

void *ptr;

ptr = malloc(sizeof(float));

Which gives you a pointer that references a space large enough to hold a float. However, you could still store an int or whatnot with that pointer, so you have to explicitly tell the compiler what you''re doing. ptr = 17.65f won''t work because you''re trying to assign to the pointer and not the memory it references. *ptr = 17.65f would work if ptr was declared as float *ptr, but it wasn''t. Therefore you need your typecasting. Breaking it down a bit, you first cast using (float *)ptr to make it a pointer to a float instead of void. Then you simply dereference it like normal with *.

I''m not sure where you think you should need typecasting in the second example, ao I''ll skip that.

In your last example, the (float *) typecast in the second line isn''t really necessary. malloc() returns a void pointer which can be safely typecast implicitly to the type of the l-value. No typecasting is necessary in the last line either, as the pointer is cast to void and no type information is passed to fread() anyway.

Hope that''s helpful, though I''m afraid I may not have made much sense.

Share this post


Link to post
Share on other sites
quote:
Original post by TheToiletDuck
So, I''ve got my void pointer, and I''ve malloc''d enough memory to hold a float:

void *ptr;
ptr = malloc(sizeof(float));

ptr = 17.65f;
This won''t work.



Correct, it shouldn''t work. ptr is a pointer (ie, a memory address) and you''re trying to give it a floating-point value? The compiler correctly flags this as an error.

quote:

*ptr = 17.65f;
Neither will this.



Again, this shouldn''t work. ptr is a pointer, but it is a pointer to void and trying to dereference (*) it makes no sense. You allocated enough memory to hold a float, but not an actual float.

quote:

*(float *)ptr = 17.65f;
This seems to be the solution, although I can''t understand why, when this is legal, assuming a couple of other declarations and a good call to fopen().

int myints[10];
fread(myints, sizeof(int)*10, 1, somefile);
Now, why no casting with fread()?




Yes, if you require that ptr be a pointer to void, then this is the correct solution. You first force the compiler to recognize it as pointer to float with the (float*) typecast, and THEN you dereference it. Since the compiler temporarily recognizes the void pointer as a float pointer, dereferencing gives you a float.

In the second part, the first parameter of fread is a void* . While you have not put in a typecast, the compiler has. It is allowed to automatically cast to void*, but not always from void*. (Actually, in C++, I think the compiler is never allowed to cast from void*.)

quote:

Is there any other strange legailties with casting like this?
such as:

float *flptr;
flptr = (float *)malloc(sizeof(float));
fread(flptr, sizeof(float), 1, somefile);

Do I need a cast then?



Not in the fread call. The compiler will automatically typecast flptr to void* in the call to fread. Same as above.


---- --- -- -
Blue programmer needs food badly. Blue programmer is about to die!

Share this post


Link to post
Share on other sites