-4
  1. When I use fwrite to stdout it becomes undefined results?
  2. What is the use of the size_t count argument in fwrite and fread function?
#include<stdio.h>

struct test
{
   char str[20];
   int num;
   float fnum;
}; 

int main()
{
   struct test test1={"name",12,12.334};

   fwrite(&test1,sizeof(test1),1,stdout);

   return 0;
}

output:

 name                   XEA
 Process returned 0 (0x0)   execution time : 0.180 s
 Press any key to continue.

And when i use fwrite for file

 #include<stdio.h>
 #include<stdlib.h>

 struct test
 {
  char str[20];
  int num;
  float fnum;
 };

 int main()
 {
 struct test test1={"name",12,12.334};
 FILE *fp;

 fp=fopen("test.txt","w");

 if(fp==NULL)
 {
   printf("FILE Error");
   exit(1);
 }

 fwrite(&test1,sizeof(test1),1,fp);

 return 0;
 }

The File also contains like this

 name                   XEA
  1. Why is the output like this?
  2. And when I put size_t count as 5, it also becomes undefined result. What is the purpose of this argument?
Clifford
  • 88,407
  • 13
  • 85
  • 165

1 Answers1

1

In the way that you're using it, fwrite is writing "binary" output, which is a byte-for-byte representation of your struct test as in memory. This representation is not generally human-readable.

When you write

struct test test1 = {"name", 12, 12.334};

you get a structure in memory which might be represented like this (with all byte valuess in hexadecimal):

test1: str: 6e 61 6d 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
       num: 0c 00 00 00
      fnum: 10 58 45 41

Specifically: 0x6e, 0x61, 0x6d, and 0x65 are the ASCII codes for the letters in "name". Your str array was size 20, so the string name is 0-terminated and then padded out with 15 more 0 characters. 0x0c is the hexadecimal representation of the number 12, and I'm assuming that type int is 32 bits or 4 bytes on your machine, so there are 3 more 0's there, also. (Also I'm assuming your machine is "little endian", with the least-significant byte of a 4-byte quantity like 0x0000000c coming first in memory.) Finally, in the IEEE-754 format which your machine uses, the number 12.334 is represented in 32-bit single-precision floating point as 0x41455810, which is again stored in the opposite order in memory.

So those 28 bytes (plus possibly some padding, which we won't worry about for now) are precisely the bytes that get written to the screen, or to your file. The string "name" will probably be human-readable, but all the rest will be, literally, "binary garbage". It just so happens that three of the bytes making up the float number 12.334, namely 0x58, 0x45, and 0x41, correspond in ASCII to the capital letters X, E, and A, so that's why you see those characters in the output.

Here's the result of passing the output of your program into a "hex dump utility:

 0  6e 61 6d 65 00 00 00 00  00 00 00 00 00 00 00 00   name............
16  00 00 00 00 0c 00 00 00  10 58 45 41               .........XEA    

You can see the letters name at the beginning, and the letters XEA at the end, and all the 0's and other binary characters in between.

If you're on a Unix or Linux (or Mac OS X) system, you can use tools like od or hexdump to get a hex dump similar to the one I've shown.


You asked about the "count" argument to fwrite. fwrite is literally designed for writing out binary structures, just like you're doing. Its function signature is

size_t fwrite(void *ptr, size_t sz, size_t n, FILE *fp);

As you know, ptr is a pointer to the data structure(s) you're writing, and fp is the file pointer you're writing it/them to. And then you're saying you want to write n (or 'count') items, each of size sz.

You called

fwrite(&test1, sizeof(test1), 1, fp);

The expression sizeof(test1) gives the size of test1 in bytes. (It will probably be 28 or so, as I mentioned above.) And of course you're writing one struct, so passing sizeof(test1) and 1 as sz and n is perfectly reasonable and correct.

It would also not be unreasonable or incorrect to call

fwrite(&test1, 1, sizeof(test1), fp);

Now you're telling fwrite to write 28 bytes, each of size 1. (A byte is of course always size 1.)

One other thing about fwrite (as noted by @AnttiHaapala in a comment): when you're writing binary data to a file, you should specify the b flag when you open the file:

fp = fopen("test.txt", "wb");

Finally, if this isn't what you want, if you want human-readabe text output instead, then fwrite is not what you want here. You could use something like

printf("str: %s\n", test1.str);
printf("num: %d\n", test1.num);
printf("fnum: %f\n", test1.fnum);

Or, to your file:

fprintf(fp, "str: %s\n", test1.str);
fprintf(fp, "num: %d\n", test1.num);
fprintf(fp, "fnum: %f\n", test1.fnum);
Steve Summit
  • 45,437
  • 7
  • 70
  • 103