C language uses macros to customize printable enum types

1. Preface:

Talk nonsense. If you are in a hurry, please skip it and see the implementation later.

Although I am very disgusted with the macro definition in C language, especially the abuse of macro definition will often make the problem confusing, but I have to admit that it is indeed very useful in some cases, such as today's example.

Our code involves fault codes or state machines. Many people will use macro definitions or enumerations to express them. Personally, I prefer the latter, because it can avoid redefinition and other problems during compilation. However, compared with other high-level languages, C is more machine friendly than programmer friendly. Although the conventional enumeration type is much more intuitive than the original magic number in the coding stage, the number printed by default will often confuse people in the debugging stage without special treatment. So for the convenience of debugging, today we try to use macro definition to implement a enumeration type of our own, so that after the definition is completed, friendly strings can be printed when printing It's not a number.

2. text

1. Public code

// def_enums.h
#ifndef DEF_ENUMS_H
#define DEF_ENUMS_H

#define GENERATE_ENUM(ENUM) ENUM,
#define GENERATE_ENUM_STRING(STRING) #STRING,

// Define enumeration type
#define DEF_ENUM_TYPE(name, ENUMS, start) \
    enum ENUM_##name {                    \
    name##_START = start,                 \
    ENUMS(GENERATE_ENUM)                  \
    name##_END                            \
    }

// Define enumeration type description string
#define DEF_ENUM_STRING(name, ENUMS)  \
    const char* name##_STR[] = {      \
        #name##"_start"               \
        ENUMS(GENERATE_ENUM_STRING)   \
        #name##"_end"                 \
    }


#endif


2. Use example

// main.c
#include <stdio.h>
#include "def_enums.h"

/* User use example */

// Defined in header / source file
#define USER_ENUMS(GENERATE)                     \
    GENERATE(ENUM_1)                             \
    GENERATE(ENUM_2)                             \
    GENERATE(ENUM_3)                             \
    GENERATE(ENUM_4)                             \
    GENERATE(ENUM_5)

DEF_ENUM_TYPE(MY_ENUM, USER_ENUMS, 0);
extern const char* MY_ENUM_STR[];

// Defined in source file
DEF_ENUM_STRING(MY_ENUM, USER_ENUMS); // Note to define in source file, cannot define to header file

int main()
{
    ENUM_MY_ENUM tmp = ENUM_2;
    printf("tmp = %s\n", MY_ENUM_STR[tmp]);

    // Cycle print enumeration values
    for (int i = MY_ENUM_START; i <= MY_ENUM_END; i++)
    {
        printf("%d = %s\n", i, MY_ENUM_STR[i]);
    }
}

Tags: C

Posted on Wed, 18 Mar 2020 10:24:58 -0400 by neroag