C typedef correct use case

Viewed 113

I am defining a bunch of variables in C (For context these variables are the types of chunks you can find in a png). There are 21 in total, and each is 4 letters long. So far, I have been representing them with unsigned char[4], like such:

unsigned char BKGD_CHUNK[4] = {'b', 'K', 'G', 'D'};
unsigned char CHRM_CHUNK[4] = {'c', 'H', 'R', 'M'};
unsigned char DSIG_CHUNK[4] = {'d', 'S', 'I', 'G'};
unsigned char EXIF_CHUNK[4] = {'e', 'X', 'I', 'f'};
unsigned char GAMA_CHUNK[4] = {'g', 'A', 'M', 'A'};

I was wondering if instead of doing this, I should create a new type, maybe called TYPE, defined as unsigned char[4]. I was looking up the use cases for typedef, and saw that some sources say it should be used when the lack of it would make things wordy due to repeated use. While there are only 21 possible chunk types, so it would not be repeatedly used, I felt as if I should still ask here.

I also am aware that when using typedef like this it changes the values to a pointer, however in my case this does not matter much and I could do with this it if i should in fact be using typedef.

3 Answers

This is one of the ways to go in such cases.

#include <stdio.h>

typedef struct CHUNKS {
    unsigned char CHUNK[4];
}CHUNKS;

int main()
{
    CHUNKS BKGD = {'b', 'K', 'G', 'D'};
    CHUNKS CHRM = {'c', 'H', 'R', 'M'};
    CHUNKS DSIG = {'d', 'S', 'I', 'G'};
    CHUNKS EXIF = {'e', 'X', 'I', 'f'};
    CHUNKS GAMA = {'g', 'A', 'M', 'A'};
    
    printf("%c %c\n", GAMA.CHUNK[0], GAMA.CHUNK[1]);

    return 0;
}

TYPE, defined as unsigned char[4]

Do not do:

typedef unsigned char TYPE[4];

Typedef arrays are very confusing.

TYPE some_normal_function(); // ERROR - function cannot return an array
int some_function(TYPE var) {
     TYPE a = var; // ERROR - can't assign to array
     return sizeof(var); // returns sizeof(unsigned char*) 
                         // and __not__ sizeof(unsigned char[4])
}

Unless you do have specific and very clear requirements to use a typedef arrays and you know what you're doing, do not use a typedef arrays. Using typedef pointers is also confusing for most cases and preferably shouldn't be used. Just use a normal structure with an array inside as a member, as presented in the other answer.

Note that by convention UPPER CASE IDENTIFIERS are meant to be used for macros - other programmer will assume that TYPE is a macro which may be confusing. Prefer lowercase variables.

some sources say it should be used when the lack of it would make things wordy due to repeated use.

Those sources are incorrect. You don't use a typedef to reduce keystrokes, you use it to abstract away implementation details that the programmer doesn't need to know in order to use that type.

Think of the FILE type in the standard library - this is a typedef for a type that manages the state of a stream. It is also supported by an entire API for opening, reading, writing, and closing streams such that you don't have to manipulate a FILE object directly.

If the user of your type has to know it's a 4-element array of char in order to use it properly, then don't hide it behind a typedef. Otherwise you've created a "leaky" abstraction that will be confusing to use. If you hide the type's array-ness behind a typedef name, then you should also create a full API to manage objects of that type.

Related