3

Is fwrite portable? I'm not really faced to the problem described below but I'd like to understand the fundamentals of C.

Lest assume we have two machines A8 (byte = 8bits) and B16 (byte = 16 bits).

Will the following code produce the same output on both machines ?

unsigned char[10] chars;
...
fwrite(chars,sizeof(unsigned char),10,mystream);

I guess A8 will produce 80 bits (10 octets) and B16 will produce 160 bits (20 octets). Am I wrong?

This problem won't appear if only uintN_t types were used as their lengths in bits are independent of the size of the byte. But maybe uint8_t won't exist on B16.

What is the solution to this problem?

I guess building an array of uint32_t, putting my bytes in this array (with smart shifts and masks depending on machine's architecture) and writing this array will solve the problem. But this not really satisfactory.There is again an assumption that uint32_t exists on all platforms.The filling of this array will be very dependant on the current machine's architecture.

Thanks for any response.

mvera
  • 904
  • 12
  • 23
  • "But maybe uint8_t won't exist on B16." It can't, nothing except bit-fields can be smaller than a `char`. – Daniel Fischer Jul 27 '12 at 09:40
  • `sizeof(char)` is **always** 1. – Kerrek SB Jul 27 '12 at 09:45
  • "I guess A8 will produce 80 octets and B16 will produce 160 octets. Am I wrong?" Yes, it will be 80 resp. 160 **bits** or 10 resp. 20 **octets**. – Daniel Fischer Jul 27 '12 at 09:54
  • Short answer: the code can be portable, the resulting data can be not portable. A machine can have any wordsize, CHAR_BIT or endianness. The word "octet" is used by the network-people to ensure their assumption of 8-bit bytes. Implementations (for TCP/IP) that happen to have different CHAR_BIT values should behave "AS-IF". – wildplasser Jul 27 '12 at 10:18
  • Thanks Daniel for your comments, I corrected from octets to bits. Yes wildplasser I forgot the other problem of endianness. – mvera Jul 27 '12 at 10:26
  • @KerrekSB, `sizeof(char)` is always `1` memory cell but the number of **bits** behind this one memory cell could differ. – Hristo Iliev Jul 27 '12 at 10:46
  • 1
    @mvera - There is no endianness for a `char`, it has only got one 'end'. – Bo Persson Jul 27 '12 at 12:11
  • For those wondering when a byte != 8 bits - http://stackoverflow.com/questions/5516044/system-where-1-byte-8-bit – RyPeck Aug 01 '13 at 21:27

3 Answers3

2

fwrite() is a standard library function. So it must be portable for each C compiler. That is it must be defined in C standard library of that compiler to support your machine.

So machine of 8bit, 16 bit, 32 bit give you same high level operation.

But if you want to design those library function then you have to consider machine architecture, memory organization of that machine.

As a C compiler user you should not bother about internal behavior.

I think you just want to use those C library function. So no difference in behavior of the function for different machine.

RyPeck
  • 7,830
  • 3
  • 38
  • 58
rajesh6115
  • 705
  • 9
  • 21
0

A byte is on almost every modern computer 8 bits. But there is an other reason fwrite isn't portable:
A file which was written on a Little Endian machine can't be readed by a big endian machine and other way.

qwertz
  • 14,614
  • 10
  • 34
  • 46
  • That's wrong, in C, a byte is always `CHAR_BIT` bits. The only guarantee you have is that it's _at least_ 8. – Daniel Fischer Jul 27 '12 at 09:55
  • This only applies to types that span more than one memory cell, e.g. 16-/32-/64-bit integer types or floats. Arrays of characters (essentially strings) are always laid out in memory and on disk exactly the same way on both BE and LE machines. – Hristo Iliev Jul 27 '12 at 10:50
0

In C, char is defined as "smallest addressable unit of the machine". That is, char is not necessarily 8 bits.

In most cases, it's safe enough to rely on a fact that char is 8 bits, and not to deal with some extreme cases.

To speak generally, you probably won't be able to write "half of a byte" to a file on a storage. Additionally, there will be issues with portability on hardware level between devices which are designed to work with different byte size machines. If you are dealing with other devices (such as telecom or stuff), you will have to implement bit streams.

Senna
  • 368
  • 1
  • 5