I have this code here:
Void() aba ()
{
}
#define std_Dynamic_Array(T) struct{Int32() count; Int32() capacity; T* memory; }
Void() no_body_func (Int32() b);
Int32() test_func (Int32()*** a)
{
}
Int32() test_func2 (Int32() x)
{
}
Int32() b = 33;
#define v_macro(T) struct{Int32() count; Int32() capacity; T* memory; } v (std_Dynamic_Array(T)* m) \
{ \
Int32() l = 44; \
}
Void() _main ()
{
Int64() a = 5;
b = 22;
Int32() c = test_func2(6);
Int32() inner_func (Int32()* a)
{
Int32() g = 3;
}
Int32()* x = &b;
inner_func(x);
Int32() j = *x;
Float32() f = 33.000000;
std_Dynamic_Array(Int64()) da = {.count = 4};
v_macro(Int64());
std_Dynamic_Array(Int64()) k = v(&da);
}
int main(int argc, char ** argv)
{
return 0;
}
I'm playing around with writing my own compiler that can generate C code as one of the targets. My problem is that I'm getting this weird error:
tests/simple.c:34:36: error: invalid initializer
34 | std_Dynamic_Array(Int64()) k = v(&da);
| ^
Here's code generated by gcc -E ...
void aba ()
{
}
void no_body_func (int b);
int test_func (int*** a)
{
}
int test_func2 (int x)
{
}
int b = 33;
void _main ()
{
long long a = 5;
b = 22;
int c = test_func2(6);
int inner_func (int* a)
{
int g = 3;
}
int* x = &b;
inner_func(x);
int j = *x;
float f = 33.000000;
struct{int count; int capacity; long long* memory; } da = {.count = 4};
struct{int count; int capacity; long long* memory; } v (struct{int count; int capacity; long long* memory; }* m) { int l = 44; };
struct{int count; int capacity; long long* memory; } k = v(&da);
}
int main(int argc, char ** argv)
{
return 0;
}
Why is this error happening? Both v
's return type and k
's type expand to struct{int count; int capacity; long long* memory; }
, so why does GCC treat them as different types?
What can I possibly do to fix this?
Also:
I know I could probably solve this by generating some typedefs, but I want to avoid that. For now at least.
Thanks!!
Every definition of a structure creates a distinct type, and this is a deliberate and desirable feature of C. If we have:
typedef struct { double a, b; } GeometricPoint;
typedef struct { double a, b; } ComplexNumber;
then we want GeometricPoint
and ComplexNumber
to be different types so that one cannot be accidentally assigned to the other, even if their layout is identical.
Everywhere in your code that you have struct{int count; int capacity; long long* memory; }
, you have a different type, and each of these types is incompatible with the others, and thus you get warnings and errors when trying to assign one to another, to pass one as an argument for another, or to try assignments or argument passing with pointers to them.
To fix this, declare the structure once with a tag:
struct MyStructure { int count; int capacity; long long *memory; };
and then use only struct
with the tag, struct MyStructure
, throughout the rest of the code. Alternately, you can use a typedef
:
typedef struct { int count; int capacity; long long *memory; } MyStructure;
and then use the typedef
name, MyStructure
, throughout the rest of the code.