Personally, I'd make a tag in the record itself which denotes its type. I'd make this the first entry in the record.
1) read the tag,
2) backup just before the tag
3) read the whole record based on the tag
Additionally, you could stick the three records in a union, and read it that way, then validate your records once you've read them. This would mean that when you write them, in binary, the records would end up taking up the same space on disk. The benifit of this is that it provides for fast seek times / lookups.
fread( &tag, sizeof(int), 1, fp );
fseek( fp, -sizeof(int), SEEK_CUR );
fread( tag == 1 ?
&rec1, sizeof(rec1) : tag == 2 ?
&rec2, sizeof(rec2) :
&rec3, sizeof(rec3) ,
1, fp );