1

I am trying to pass a variable name to a macro in C code. and need to identify whether it is an array or not run time. Is it possible to do in C?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Coder
  • 9
  • 3
  • 4
    A code example might clarify your requirement, – Martin James Jun 02 '15 at 09:51
  • 2
    Macros are just syntactic features. They don't care about types. If you pass an array and use it as a struct the code will not compile (and the converse). But give us more hint about what you really want to do... – Jean-Baptiste Yunès Jun 02 '15 at 09:52
  • No, there's no such thing as "a variable whose type I don't know" in C. The closest you can come is `void *`, but that will not be so easy to use. And no, there's no run-time type information. – unwind Jun 02 '15 at 09:53
  • 1
    It is impossible. The best you can do is write two macros: `#define MACRO_PLAIN ...` and `#define MACRO_ARRAY ...` – pmg Jun 02 '15 at 09:54
  • Related: https://stackoverflow.com/questions/19452971/array-size-macro-that-rejects-pointers/ – M.M Jul 19 '18 at 03:03

2 Answers2

2

Generally not possible, but there are a few cases where you could make it work:

If the arrays are allocated statically:

For example int arr[N]; or int arr[] = {1,2,3};:

#define IS_ARRAY(x)  ((void*)(x) == (void*)&(x))

This works because if the array was declared as above, arr is the same as &arr and &arr[0]. That is because while the array does act as a pointer, no memory is actually allocated for that pointer, so you cannot get it's address. & operator returns the address of the first element.

This will not work if your array is actually a pointer, such as int *arr = malloc(3*sizeof(int));

If your variables are always a primitive type

Using C11 feature for type generic expressions, you can do:

#define IS_ARRAY(x) _Generic((x), default:1,char:0,short:0,int:0,long:0,float:0,double:0,long double:0)

This will return 0 for only those types of x, and 1 for any other, including arrays.

If your arrays are bigger than your variables

For the sake of completeness, I'm listing this:

#define IS_ARRAY(x)  (sizeof(x) > SOME_VALUE)

This will be true if your array was allocated such that it is bigger than all your non-array variables. You're better off using the first approach in all cases, though.

mtijanic
  • 2,872
  • 11
  • 26
  • The problem is the structure has variables of different data types so, size cannot be "the" factor always. First approach would work for me, as the arrays are allocated statically. Thanks for the quick response – Coder Jun 03 '15 at 05:43
0

Actually, I don't think the comments are quite correct if you're fully in control of the code and can lock down certain things - i.e. the type of array and some constraints on the data sizes. It's easier to look at a contrived example:

#include <stdio.h>

int array[10] = {0};
int not_array = 10;

#define PRINT_RESULT( x ) do { \
    if( sizeof( x ) == sizeof( int ) ) { \
        printf( "Int result: %d\n", (int)x ); \
    } else {  \
        printf( "Array result: " ); \
        for( int _i = 0; _i < ( sizeof( x ) / sizeof( ((int*)x)[0] ) ); _i++ ) { \
            printf( "%02X ", ((int*)x)[_i] ); \
        } \
        printf( "\n" ); \
    } } while( 0 )

int main( int argc, char* argv[] )
{
    PRINT_RESULT( not_array );
    PRINT_RESULT( array );
    return 0;
}

Compile with gcc -Wall -std=gnu99 main.c

Run and get:

Int result: 10
Array result: 00 00 00 00 00 00 00 00 00 00

In this way, the macro does indeed deal with either an int or array of ints, but only within certain constraints. Sure, it's not exactly pretty!

Brian Sidebotham
  • 1,706
  • 11
  • 15