I want to create a generic selector for 2D array in C

Viewed 94

In case if 2d array is of float type I want to call the first function and otherwise the second, how can I accomplish this?

 void printff(int n,float m[n][n])
    {
        for(int i=0;i<n;i++){
        for(int j=0;j<n;j++)
        printf("\t%f",m[i][j]);
        printf("\n");
        }
    }
    
void printfi(int n,int m[n][n])
{
    for(int i=0;i<n;i++){
    for(int j=0;j<n;j++)
    printf("\t%d",m[i][j]);
    printf("\n");
    }
}

#define print(a,b) _Generic(b,int*[sizeof(a)]:printfi,float*[sizeof(a)]:printff)(a,b)
1 Answers

The macro should be:

#define print(a,b) _Generic((b), int(*)[]: printfi, float(*)[]: printff)((a), (b))

the type of b is either int(*)[a] or float(*)[a], e.g. a pointer to an array of a int or float.

This code works for me:

#include <stdio.h>

void printff(int n,float m[n][n])
{
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++)
            printf("\t%f",m[i][j]);
        printf("\n");
    }
}
    
void printfi(int n,int m[n][n])
{
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++)
            printf("\t%d",m[i][j]);
        printf("\n");
    }
}

#define print(a,b) _Generic((b), int(*)[]: printfi, float(*)[]: printff)((a), (b))

int main()
{
    float a[5][5];
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
            a[i][j] = i * 5 + j;
    print(5, a);
    int b[2][2];
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            b[i][j] = i * 2 + j;
    print(2, b);
}

https://godbolt.org/z/zrP9TnEcP

If you only use square 2D arrays, you can use this macro:

#define print(a) _Generic((a), int(*)[]: printfi, float(*)[]: printff)(sizeof *(a) / sizeof **(a), a)

It will calculate the length itself. Call it with print(a); or print(b);.

https://godbolt.org/z/xP918sn1s

It can be even easier when you use **(a) for the first parameter of _Generic:

#define print(a) _Generic(**(a), int: printfi, float: printff)(sizeof *(a) / sizeof **(a), (a))

https://godbolt.org/z/TzrY1G4ev

Related