Neva
Neva

Reputation: 1330

Portability concern

I have written a program that does all sorts of processing and write/reads the results in a file.

This "result" is in a struct like this

struct res
{
    char  id;
    char* values;
    int   count; 
    long  samplenumber;
};

and let's say I write/ read with functions like these

write( file, &result, sizeof(struct res) );
read(file, &result, filesize(file) );

My concern is : What could go wrong if the struct is written on a 32b machine and read on a 64 (and other way around) ?

I'm not asking for any improvements of what I'm currently doing, but just about the issues with the way things work in terms of portability.

Upvotes: 2

Views: 88

Answers (2)

HolyBlackCat
HolyBlackCat

Reputation: 96579

There are 4 problems here:

~ Sizes of types can be different. (Use types from stdint.h like uint32_t.)

~ Compiler usually will insert padding into your struct, like

struct res
{
    char  id;
    /* unused byte */
    /* unused byte */
    /* unused byte */
    char* values;
    int   count; 
    long  samplenumber;
};

~ Endianness of integers can be different. For example, 3555896322 can be represented as
D3 F2 AC 02 or 02 AC F2 D3.

~ char* will be saved to file as useless pointer. You need to write string yourself, byte by byte.

Solution:

~ Use types from stdint.h.

~ Don't use structs for saving. (Or use so called #pragma pack, but keep in mind that it's not portable.)

~ Write integers byte by byte, like

uint32_t var = 3555896322;
putc(var >>  0 & 0xff, file);
putc(var >>  8 & 0xff, file);
putc(var >> 16 & 0xff, file);
putc(var >> 24 & 0xff, file);

~ Write strings byte by byte, for example:

const char *ptr = "Hello, young programmer!";
while (*ptr)
    putc(*(ptr++), file);
putc('\0', file);

~ Floating-point types can be saved directly, they usually have same size everywhere:

float a = 1.23;
fwrite(&a, sizeof (float), 1, file);

Upvotes: 4

myaut
myaut

Reputation: 11504

From my experience, everything will go wrong because sizes of types are different on platforms.

First of all replace types with ones from stdint.h

#include <stdint.h>

struct res
{
    uint8_t   id;
    char*     values;
    uint32_t  count; 
    uint32_t  samplenumber;
};

Your also shouldn't write string as char*. When you read it again you just get stale pointer. Use string of predefined size:

 char values[256];

Or write string manually in a separate write call.

Upvotes: 3

Related Questions