Search code examples
carraysmacroscompile-time

is there a way to know (and not fail) at compile time if this is a array or an integer?


OP:

is there a way to know at compile time if the current object is an array or an integer?

#include <stdio.h>

#define IS_INDEXABLE(arg) (sizeof(arg[0]))
#define IS_ARRAY(arg) (IS_INDEXABLE(arg) && (((void *) &arg) == ((void *) arg)))

int main(void)
{
    int a[5]; // array
    int *b = a; // pointer
    int n = 10;
    int c[n]; // VLA
    int d = 4; // integer

    printf("%d\n", IS_ARRAY(a)); //works, 1
    printf("%d\n", IS_ARRAY(b)); //works, 0 (edit: I want it to be 1)
    printf("%d\n", IS_ARRAY(c)); //works, 1 
    printf("%d\n", IS_ARRAY(d)); //should say 0, but does not compile "error: subscripted value is neither array nor pointer nor vector"
    return 0;
}


edited answer:

After reflexion I ended up with the following observation:

Most of the anwers were correct for the first part of the problem, and my proposition was also working.

#define IS_ARRAY1(arg) (((void *) &arg) == ((void *) arg))
#define IS_ARRAY2(arg,type) ((sizeof(arg)/sizeof(type) != 1) && (sizeof(arg)/sizeof(type) != sizeof(arg)))
#define IS_ARRAY4(x,type) _Generic((&x), \
                          type (*)[]: 1, \
                          default:   0)

The second part of the problem will be treated here thank you.


Solution

  • Since _Generic is based on the requirement that the expression should be compared for type compatibility with everything in the "association list", you can do like this:

    #define IS_INT_ARRAY(x) _Generic((&x),          \
                                     int (*)[]: 1,  \
                                     default:   0)
    

    In case the parameter is an int array , then it will be compatible with an array pointer to an int array of incomplete type (unknown size).

    In case the parameter is an object pointer, you may apply & but it will not result in an array pointer.