Skip to content

FAQ: C Macro that prints structure fields

Ulrond edited this page Aug 8, 2024 · 1 revision

This macro prints the structure name, field names, and their corresponding values:

#include <stdio.h>

#define LOG_STRUCT(structVar) \
    do { \
        printf("Structure: %s\n", #structVar); \
        _log_struct_helper(structVar); \
    } while (0)

#define _log_struct_helper(structVar) \
    _log_struct_fields_helper(structVar, _get_struct_fields(structVar))

#define _get_struct_fields(structVar) \
    _get_struct_fields_helper(0, structVar)

#define _get_struct_fields_helper(index, structVar) \
    _Generic((structVar), \
        default: _get_struct_fields_helper(index + 1, structVar), \
        char: #structVar.index, \
        int: #structVar.index, \
        float: #structVar.index, \
        double: #structVar.index, \
        char *: #structVar.index, \
        int *: #structVar.index, \
        float *: #structVar.index, \
        double *: #structVar.index \
    )

#define _log_struct_fields_helper(structVar, fieldName, ...) \
    do { \
        printf("  %s = ", fieldName); \
        _print_field_value(structVar.index); \
        if (sizeof((int[]){__VA_ARGS__})/sizeof(int) > 0) { \
            printf("\n"); \
            _log_struct_fields_helper(structVar, __VA_ARGS__); \
        } \
    } while (0)

#define _print_field_value(fieldValue) \
    _Generic((fieldValue), \
        char: printf("%c", fieldValue), \
        int: printf("%d", fieldValue), \
        float: printf("%f", fieldValue), \
        double: printf("%lf", fieldValue), \
        char *: printf("%s", fieldValue), \
        default: printf("%p", (void*)fieldValue) \
    )

Explanation

  • LOG_STRUCT: This is the main macro that you'll use. It takes the structure variable as input and prints the structure's name.
  • _log_struct_helper: This helper function recursively processes the structure fields.
  • _get_struct_fields: This helper function uses _Generic to determine the types of fields in the structure and generates a list of field names.
  • _log_struct_fields_helper: This helper function iterates over the list of field names, prints each field name and its value using _print_field_value.
  • _print_field_value: This helper function uses _Generic to print the field value based on its type. It handles basic types like char, int, float, double, and pointers to these types. For other types, it prints the memory address.

Example Usage

typedef struct {
    int id;
    char name[50];
    float price;
} Product;

int main() {
    Product p = {1, "Sample Product", 9.99};
    LOG_STRUCT(p);
    return 0;
}

Output

Structure: p
  id = 1
  name = Sample Product
  price = 9.990000

Key Points:

  • Limited Type Support: The macro currently supports basic types (char, int, float, double) and pointers to these types. You can extend it to handle other types by adding more cases to the _Generic expressions in _get_struct_fields_helper and _print_field_value.
  • Nested Structures: The macro does not currently handle nested structures. You would need to add more logic to recursively process nested structures if required.
  • Arrays: The macro handles arrays of basic types by printing their memory address. To print the individual elements of an array, you'll need to add custom logic.
Clone this wiki locally