A purpose of a macro is that it is replaced by something else (whatever that macro is defined to be) by the pre processor.
Specifically, placing a macro between class-key and the class name (such as in your example), will let the macro control the attribute sequence of the class. For example, if you define the macro to be empty (such as in your example), then the class will have an empty attribute sequence:
#define GS
struct GS gs {
// same as
struct gs {
But a macro can be defined to be non-empty:
#define GS alignas(8)
struct GS gs {
// same as
struct alignas(8) gs {
Macros can be passed as an argument to the tool chain upon compilation, thereby toggling a feature on or off. Macros can also be used to detect the target system and thereby enable system specific code - thereby allowing a system dependent program work on multiple systems.
Another purpose of a macro is to prevent a header from being included twice. Such macro is called a header guard. Using the same macro for both a header guard, and content replacement (such as in your example) is confusing and unconventional.