tags:

views:

210

answers:

3

Lets say I have a "Passenger" struct, which has a field for a name.

If I do (like the syntax of my book shows):

fread(&passenger, sizeof(Passenger), 1, in_fp);
printf("%s", (*passenger).first_name)

I get a segmentation fault, but if I do:

fread( (char *)passenger, sizeof(Passenger), 1, in_fp);
printf("%s", (*passenger).first_name)

the name read from the file will be printed out.

+8  A: 

Looks to me as if 'passenger' is a pointer. If you take &passenger, you are passing the address of the pointer to fread. When you cast it, you are telling fread to treat it as a pointer to a char buffer instead of a pointer to a Passenger.

bmargulies
kevin
That cannot be true, given the line of code (*passenger).first_name. It's a pointer.
bmargulies
Well, Passenger could be a typedef for `(struct passenger_struct *)` :)
hobbs
Then the part that isn't true is "Lets say I have a 'Passenger' struct".
Steve Jessop
If `passenger` was a struct object (not a pointer), neither `(char *) passenger` nor `*passenger` would compile. `passenger` is a pointer in your code, there's no way around it.
AndreyT
+3  A: 

You probably have a pointer to a Passenger, not a Passenger:

fread(passenger, sizeof(Passenger), 1, in_fp); printf("%s", (*passenger).first_name)

Will most likely do what you want.

drhirsch
So, since I gave the address of "passenger" by calling it, I don't need the ampersand correct?
kevin
kevin
drhirsch
+2  A: 

In the early days of C language, C had no void * type (it appeared later, was borrowed from C++ actually) and type char * was used as the generic "raw memory" pointer type instead. So, even to this day you might see this habitual rudimentary use of type char * as the generic pointer type in the code, and see other pointer types explicitly converted to and from char * in generic pointer context. I'd guess that the code you quoted does this for that specific reason. (Unless it was you who put this char * cast there. In that case I can only ask "Why?".)

In modern C the first parameter of fread has void * type, meaning that no cast is necessary. This

fread(passenger, sizeof *passenger, 1, in_fp);

whill work just as well.

Your &passenger version makes no sense, since apparently the original intent was to read data into the location passenger points to, not into the passenger pointer object itself.

AndreyT
Even using char* instead of void*, no cast would be necessary.
Roger Pate
do you mind if I copy your historical disquisition into my answer to make it more complete?
bmargulies
No, I don't mind.
AndreyT