Search code examples
cpreprocessor

Is there a way to initialize a variable to a default value without knowing its type in C?


I'm playing around with macros and I managed to do a stack structure that can work with any type, but the thing is I have a problem with the POP function, it has to pop the value out of the stack and return it, for that I'm using a statement expression. The thing is when the stack is empty, I have to return a default value, but I don't know the type of the variable so I can't just return NULL or INT_MIN because it can be a pointer, an integer, an array or a struct. What I want to do is initialize that variable to a default value like for static variables (they auto initialize to either 0 or {}). Here is the code I wrote for the context. (The code works but when POP fails it returns an undefined uninitialized value, so it can't compile with -Wall -Wextra -Werror)

#ifndef STACK_H
# define STACK_H

# include <sys/types.h>
# include <stdint.h>
# include <stdbool.h>
# include <stdlib.h>

# define STACK(type, cap) struct {\
    size_t  capacity;\
    size_t  size;\
    type    data[cap];\
}\

# define STACK_INIT(stack) \
(stack) = (typeof(stack)) {\
    .capacity = sizeof((stack).data) / sizeof(*(stack).data),\
    .size = 0,\
    .data = {}\
}

# define STACK_PUSH(stack, value) ({\
    bool    ret = true;\
\
    if ((stack).size == (stack).capacity) ret = false;\
    (stack).data[(stack).capacity - ++(stack).size] = value;\
    ret;\
})

# define STACK_POP(stack) ({\
    typeof(*(stack).data)   ret;\ // Here ret is declared
\
    if ((stack).size) ret = (stack).data[(stack).capacity - (stack).size--];\
\   // else ret is uninitialized, is it possible to give it a default value without knowing its type?
    ret;\
})

# define STACK_SIZE(stack) stack.size
# define STACK_EMPTY(stack) !stack.size

#endif

Example of simple usage:

#include <stdio.h>
#include "stack.h"

int main(int argc, char **argv) {
    if (argc < 2) {
        dprintf(2, "Usage: %s <at least one argument>\n\n", argv[0]);
        return (-1);
    }
    STACK(char *, 10) stk;
    STACK_INIT(stk);
    for (int i = 1; i < argc; ++i)
        if (!STACK_PUSH(stk, argv[i])) {
            dprintf(2, "Failed to push\n\n");
            return (-1);
        }
    while (!STACK_EMPTY(stk))
        printf("%s\n", STACK_POP(stk));
    return (0);
}

Solution

  • I don't think this is possible in C.


    But one solution is to assume that a default value is zero-byte initialized, and write code like:

    typeof(*(stack).data)   ret;   \
    memset(&ret, 0, sizeof(ret));   \