How To Write Portable Standard Structs in C

If you're sure your C source code won't ever be ported to or implemented in another UNIX (or UNIX-like) platform apart from Linux, you don't have to worry about this.

However, that may rarely be the case. Best practices and portability concerns may require you to define standard structs in a certain way. For example, consider the standard sembuf struct that defines a semaphore operation:

struct sembuf {
    unsigned short int sem_num;
    short int sem_op;
    short int sem_flg;};

On Linux, you may initialize the sembuf struct as follows and you'll have no problems:

struct sembuf buf = {10, 1, SEM_UNDO};

where SEM_UNDO is a system-defined flag.

The portability problem with the above initialization is that it assumes the structure definition is in the order shown before. While this may be correct for some other UNIX-like platforms, it will be incorrect for others. Although portability standards (e.g SUSv3) define the sembuf structure, they don't necessarily define the order of the fields in the definition. In some cases, there may even be other fields that are implementation-specific and don't exist in the Linux definition.

Using the above initialization in such cases would cause errors and unexpected behaviors.

The Solution

You should define standard structs using the dot notation. For example, the sembuf struct initialization above should be written as:

struct sembuf buf;
buf.sem_num = 10;
buf.sem_op = 1;
buf.flg = SEM_UNDO;

The dot notation version is more verbose, but it's a small price to pay to have portable programs. Fortunately, if you're using the C99 standard in your C program, you may retain the convenience of a single-line initialization as follows:

struct sembuf buf = {.sem_buf = 10, .sem_op = 1, .sem_flg = SEM_UNDO};