0
votes

Here is minimal test case of what I am trying to do;

// minimal test case
#include <stdlib.h>

struct array {
    void *ptr;
    int numElements;
    int capacity;
};

struct task {
    char *task_name;
    int task_id;
};

#define NEW_ARRAY(TYPE, VARIABLE, CAPACITY) \
    struct array VARIABLE; \
    VARIABLE.ptr = malloc(CAPACITY * sizeof(TYPE)); \
    VARIABLE.capacity = CAPACITY; \
    VARIABLE.numElements = 0 \

#define array_for_each(TYPE, ELEM, ARRAY) \
    for (int i=0, ELEM = *((TYPE *)ARRAY.ptr); \
        i<ARRAY.numElements; \
        i++, ELEM = *((TYPE *)ARRAY.ptr + i) \
    ) \

int main() {
    NEW_ARRAY(struct task, my_tasks, 2);
    struct task tmp;

    array_for_each(struct task, tmp, my_tasks) {
        ;
    }

    return 0;
}

I am getting;

test.c:22:23: hata: incompatible types when initializing type 'int' using type 'struct task' for (int i=0, ELEM = *((TYPE *)ARRAY.ptr); \

that macro line when expanded, turnes into this:

for (int i=0, tmp = *((struct task *)my_tasks.ptr); i<my_tasks.numElements; i++, tmp = *((struct task *)my_tasks.ptr + i) ) {
  ;
 }

Ok, so tmp is a struct task and I am casting my_tasks.ptr which is a void * to struct task * and dereferencing it, so that should give me a struct task. So I don't know why gcc is throwing me that error.

3
Because you're then assigning that struct task to a variable of type int? - user253751

3 Answers

2
votes

When you have code like:

for (int i=0, tmp = *((struct task *)my_tasks.ptr); ...

tmp is a new variable in the scope of the for loop and it's type is int.

1
votes

In a declaration like:

int i = 0, tmp = ....;

it is declaring ints called i and tmp. But you try to initialize this new int tmp with a struct task.

I guess you were trying to combine the declaration int i = 0; with the statement tmp = .... referring to the existing variable tmp, however that is not possible. To fix this you could hoist the ELEM= part out to before the for(.

BTW consider making the loop work with a pointer instead of copying each element by value, then you can modify the values in the array. A bonus of that approach is that you don't even need i. (You can use pointer subtraction to know when you hit the end of the loop) so you would not run into the original problem at all.

0
votes

A for loop has two different valid syntaxes. It can either be:

for (expr_opt1 ; expr_opt2 ; expr_opt3)

or

for (declartion expr_opt1 ; expr_opt2)

You are trying to mix the two by declaring a new variable, i, in the loop scope AND trying to initialize tmp. The compiler thinks you are trying to declare TWO new variables, i and tmp, both of type int, with loop scope and then initializing tmp with a struct task. The latter point is why is has an error.