fread to a struct

V

vippstar

-- foo.c --
#include <stdio.h>

int main(void) {

struct { int a; int b; } foo;
fread(&foo, sizeof foo, 1, stdin);
return 0;
}
-- foo.c --

Is there any problem with the above snippet?
In particular, with reading a struct with fread like that, instead of
reading each member seperately.
 
R

Ravishankar S

-- foo.c --
#include <stdio.h>

int main(void) {

struct { int a; int b; } foo;
fread(&foo, sizeof foo, 1, stdin);
return 0;
}
-- foo.c --

Is there any problem with the above snippet?
In particular, with reading a struct with fread like that, instead of
reading each member seperately.

What you expect may not happen. I guess stdin is opened for reading in text
mode , not binary mode.
fread and fwrite reads and writes in binary (raw bytes).
 
R

Richard Heathfield

(e-mail address removed) said:
-- foo.c --
#include <stdio.h>

int main(void) {

struct { int a; int b; } foo;
fread(&foo, sizeof foo, 1, stdin);
return 0;
}
-- foo.c --

Is there any problem with the above snippet?

Add:

printf("[%d] [%d]\n", foo.a, foo.b);

after the fread, recompile, and test. Whilst this cannot prove that there
is not a problem with the snippet, it may be able to prove that there /is/
a problem.

I doubt very much whether you will get the results you desire!
In particular, with reading a struct with fread like that, instead of
reading each member seperately.

If it was written like that, it can be read like that on the same platform
(same compiler, same switch settings, yadayadayada). So you can do this:

#include <stdio.h>
#define TESTFILE "test.foo"
int main(void)
{
struct { int a; int b; } foo = { 6, 42 };
FILE *fpw = fopen(TESTFILE, "wb");
if(fpw != NULL)
{
int ok = 0;
printf("before write: foo.a = %d\nfoo.b = %d\n", foo.a, foo.b);
fwrite(&foo, 1, sizeof foo, fpw);
ok = !ferror(fpw);
fclose(fpw);
if(ok)
{
FILE *fpr = fopen(TESTFILE, "rb");
if(fpr != NULL)
{
foo.a = 10; foo.b = 20; /* any old junk, just to prove the point */
printf("after reset: foo.a = %d\nfoo.b = %d\n", foo.a, foo.b);
fread(&foo, 1, sizeof foo, fpr);
if(!ferror(fpr))
{
printf("after read: foo.a = %d\nfoo.b = %d\n", foo.a, foo.b);
}
fclose(fpr);
}
}
}
return 0;
}

This code has been (rather cursorily) tested, and a bug removed. One kudos
point available to whoever can work out what the bug was.
 
V

vippstar

This code has been (rather cursorily) tested, and a bug removed. One kudos
point available to whoever can work out what the bug was.
I'd assume that you pass nmemb, size to fread/fwrite and not size,
nmemb.

Thanks for the replies, I know what to do now.
 
R

Richard Heathfield

(e-mail address removed) said:
I'd assume that you pass nmemb, size to fread/fwrite and not size,
nmemb.

In fact, I did get them the wrong way round, not that it matters
particularly, so well spotted, but no, that wasn't the bug (which, I
stress, was *fixed* in the posted code).
Thanks for the replies, I know what to do now.

Excellent.
 
K

Keith Thompson

Ravishankar S said:
What you expect may not happen. I guess stdin is opened for reading in text
mode , not binary mode.
fread and fwrite reads and writes in binary (raw bytes).

No, fread reads (as if) by repeated calls to fgetc. If the stream is
opened in text mode, it will read in text mode; if it's opened in
binary mode, it will read in binary mode. (Likewise for fwrite
repeatedly calling fputc.)

Because of this, reading in text mode using fread rarely makes sense;
it's *intended* to be used in binary mode.

In the above code, the fread() call will attempt to read sizeof(foo)
bytes in text mode from stdin, and store them in foo. If you're
expecting to type "10 20" and have the values 10 and 20 stored in
foo.a and foo.b, you'll be disappointed.
 
S

SM Ryan

(e-mail address removed) wrote:
# -- foo.c --
# #include <stdio.h>
#
# int main(void) {
#
# struct { int a; int b; } foo;
# fread(&foo, sizeof foo, 1, stdin);
# return 0;
# }
# -- foo.c --
#
# Is there any problem with the above snippet?

ANSI C does not guarentee sizeof struct foo will be the same
for different compilers or different versions of the same
compilers or different compilations of the same compilers.
Unless you can get a guarentee from the compilers you're
interested in, it's safer to read and write individual int
fields yourself.
 
T

Tor Rustad

-- foo.c --
#include <stdio.h>

int main(void) {

struct { int a; int b; } foo;
fread(&foo, sizeof foo, 1, stdin);
return 0;
}
-- foo.c --

Is there any problem with the above snippet?
In particular, with reading a struct with fread like that, instead of
reading each member seperately.

First problem is the *padding* issue in struct. Hence, different
versions of your compiler may break this code, or different compilers
may use different alignment of struct members, and finally just changing
compiler setting differently... may break it.

The second problem is endianness. If 'foo' is orginating from a
hetrogenious system, the code may brake.
 
K

Keith Thompson

Tor Rustad said:
First problem is the *padding* issue in struct. Hence, different
versions of your compiler may break this code, or different compilers
may use different alignment of struct members, and finally just
changing compiler setting differently... may break it.

The second problem is endianness. If 'foo' is orginating from a
hetrogenious system, the code may brake.

And the 3rd through Nth problems are all the other possible variations
in representation. For the structure shown, the possible variations
include:
Different number of bytes in an int.
Different number of bits in a byte.
Different padding bits within an int.
Different representations for negative int values.

The last three are relatively unlikely.
 

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

Similar Threads


Members online

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top