Take a look at my code:
#include <stdio.h>
#include <stdlib.h>
#define add_int(a, b) ((a) + (b))
typedef struct matrix
{
int** data;
int n_rows;
int n_columns;
} matrix;
matrix* CreateMatrix(int n_rows, int n_columns)
{
int** rows = malloc((sizeof(int*)) * n_rows);
if (!rows)
{
printf("no mallak\n");
exit(-1);
}
int iterator = 0;
while (iterator < n_rows)
{
rows[iterator] = malloc((sizeof(int)) * n_columns);
if (!rows[iterator])
{
printf("no mallak\n");
exit(-1);
}
iterator += 1;
}
matrix* returnable = malloc(sizeof(matrix) * 1);
if (!returnable)
{
printf("no mallak\n");
exit(-1);
}
returnable->data = rows;
returnable->n_rows = n_rows;
returnable->n_columns = n_columns;
return returnable;
}
void PrintMatrix(matrix* printable)
{
int row_iterator = 0, column_iterator = 0;
while (row_iterator < printable->n_rows)
{
while (column_iterator < printable->n_columns)
{
printf("%d ", printable->data[row_iterator][column_iterator]);
column_iterator += 1;
}
printf("\n");
row_iterator += 1;
column_iterator = 0;
}
printf("\n");
}
matrix* AddMatrix(matrix* addable1, matrix* addable2)
{
if ( (addable1->n_rows != addable2->n_rows) || (addable1->n_columns != addable2->n_columns) )
{
return NULL;
}
matrix* returnable = CreateMatrix(addable1->n_rows, addable1->n_columns);
int row_iterator = 0, column_iterator = 0;
while (row_iterator < addable1->n_rows)
{
while (column_iterator < addable1->n_columns)
{
returnable->data[row_iterator][column_iterator] = (addable1->data[row_iterator][column_iterator]) + (addable2->data[row_iterator][column_iterator]);
column_iterator += 1;
}
row_iterator += 1;
column_iterator = 0;
}
return returnable;
}
#define add(a, b) (_Generic(a, \
int : add_int(a, b), \
matrix* : AddMatrix(a, b) \
))
int main()
{
matrix* M1 = CreateMatrix(2, 2);
matrix* M2 = CreateMatrix(2, 2);
M1->data[0][0] = 1; M1->data[0][1] = 2;
M1->data[1][0] = 3; M1->data[1][1] = 4;
M2->data[0][0] = 5; M2->data[0][1] = 6;
M2->data[1][0] = 7; M2->data[1][1] = 8;
add(M1, M2);
}
And take a look at the error it produces:
1.c: In function 'main':
1.c:4:27: error: invalid operands to binary + (have 'matrix *' and 'matrix *')
4 | #define add_int(a,b) ((a) + (b))
| ^
1.c:104:15: note: in expansion of macro 'add_int'
104 | int : add_int(a,b), \
| ^~~~~~~
1.c:120:5: note: in expansion of macro 'add'
120 | add(M1,M2);
| ^~~
This is the command I used to compile:
gcc -std=c11 1.c -o 1.exe
The thing is, if I change the code in main() , to this:
int main()
{
int result = add(1, 5);
printf("%d\n",result);
}
The compiler produces only warnings!!! :
1.c: In function 'main':
1.c:111:26: warning: passing argument 1 of 'AddMatrix' makes pointer from integer without a cast [-Wint-conversion]
111 | int result = add(1,5);
| ^
| |
| int
1.c:105:29: note: in definition of macro 'add'
105 | matrix* : AddMatrix(a,b) \
| ^
1.c:72:27: note: expected 'matrix *' but argument is of type 'int'
72 | matrix* AddMatrix(matrix* addable1, matrix* addable2)
| ~~~~~~~~^~~~~~~~
1.c:111:28: warning: passing argument 2 of 'AddMatrix' makes pointer from integer without a cast [-Wint-conversion]
111 | int result = add(1,5);
| ^
| |
| int
1.c:105:31: note: in definition of macro 'add'
105 | matrix* : AddMatrix(a,b) \
| ^
1.c:72:45: note: expected 'matrix *' but argument is of type 'int'
72 | matrix* AddMatrix(matrix* addable1, matrix* addable2)
| ~~~~~~~~^~~~~~~~
And it executes correctly too:
6
What am I supposed to do now?
Thanks for the help. Have a good day :)
The _Generic feature introduced in C11 cannot be used the way you write in your code: it is not a preprocessing construction so each of the clauses must be syntactically correct for the compiler to select the first type match.
This restriction is a tricky shortcoming that could be considered a design flaw, but there is a simple way to modify your code to get the intended behavior:
add_int as a function that will be inlined by the compiler if selectedadd so _Generic expands to a function that is applied to the argumentsHere are the modifications:
//#define add_int(a,b) ((a) + (b))
int add_int(int a, int b) { return a + b; }
#define add(a, b) (_Generic((a), \
int: add_int, \
matrix*: AddMatrix))(a, b)
Also modify your code to store the result of add(M1, M2):
int main(void)
{
matrix *M1 = CreateMatrix(2, 2);
matrix *M2 = CreateMatrix(2, 2);
M1->data[0][0] = 1; M1->data[0][1] = 2;
M1->data[1][0] = 3; M1->data[1][1] = 4;
printf("M1:\n");
PrintMatrix(M1);
M2->data[0][0] = 5; M2->data[0][1] = 6;
M2->data[1][0] = 7; M2->data[1][1] = 8;
printf("M2:\n");
PrintMatrix(M2);
matrix *M3 = add(M1, M2);
printf("add(M1, M2):\n");
PrintMatrix(M3);
FreeMatrix(M1);
FreeMatrix(M2);
FreeMatrix(M3);
return 0;
}