Related
I have a small recursive AST as follows:
enum ABC
{
A,
B,
C
};
typedef struct abc_t
{
enum ABC kind;
union {
struct a_
{
int x;
} a_;
struct b_
{
int y;
} b_;
struct c_
{
struct abc_t **array;
} c_;
} u;
} abc_t;
To simplify the constructions, I define fill macros:
#define ABC_SET_A(n) (abc_t) { .kind = A, .u.a_ = { n } }
#define ABC_SET_B(n) (abc_t) { .kind = B, .u.b_ = { n } }
const abc_t bar = ABC_SET_A(5);
const abc_t foo = ABC_SET_B(2);
However, I don't know how to fill the "c_" branch of my AST with a macro. I would like to arrive at this result:
const abc_t test = ABC_SET_C({ABC_SET_B(4), ABC_SET_A(3), ABC_SET_B(2)});
// or
const abc_t test = ABC_SET_C(ABC_SET_B(4), ABC_SET_A(3), ABC_SET_B(2)); // With variadics arguments
The goal would be to have an immutable array of abc_t that would represent a set of pre-built structures, something like:
const abc_t pre_builds[] =
{
ABC_SET_A(10), // pre_builds[0]
ABC_SET_C({ABC_SET_A(8), ABC_SET_B(4)}), // pre_builds[1]
ABC_SET_B(23) // pre_builds[2]
...
};
I don't know how to handle a recursive structure for a such as macro, especially for an array in this case.
How do I do it?
First fix your ABC_SET_A and ABC_SET_B. You don't initialize int with braces like int var = { 1 }; , you initialize int like int var = 1;:
#define ABC_SET_A(n) (abc_t){ .kind = A, .u.a_ = n }
#define ABC_SET_B(n) (abc_t){ .kind = B, .u.b_ = n }
Doing your ABC_SET_C is easy. As you have array of pointers in your structure, you can do this:
#define ABC_SET_C(...) (abc_t){ .kind = C, .u.c_ = (abc_t*[]) __VA_ARGS__ }
const abc_t pre_builds[] =
{
ABC_SET_A(10), // pre_builds[0]
// note - as this is array of pointers, I added & to get the pointer
ABC_SET_C({&ABC_SET_A(8), &ABC_SET_B(4)}), // pre_builds[1]
ABC_SET_B(23) // pre_builds[2]
};
The { } braces are not special to preprocessor anyway and not parsed by it. I would prefer:
#define ABC_SET_C(...) (abc_t){ .kind = C, .u.c_ = (abc_t*[]) { __VA_ARGS__ } }
const abc_t pre_builds[] =
{
ABC_SET_A(10), // pre_builds[0]
ABC_SET_C(&ABC_SET_A(8), &ABC_SET_B(4)), // pre_builds[1]
ABC_SET_B(23) // pre_builds[2]
};
If you want to get rid of writing & in front of every ABC_SET_*, then you can overload the macro on number of arguments and insert them per each argument. I find it not worth the effort, but it may be implemented like this for up to 3 arguments:
#define ABC_SET_A(n) ((abc_t){ .kind = A, .u.a_ = n })
#define ABC_SET_B(n) ((abc_t){ .kind = B, .u.b_ = n })
#define ABC_SET_C_1(_1) &_1
#define ABC_SET_C_2(_1,_2) &_1, &_2
#define ABC_SET_C_3(_1,_2,_3) &_1, &_2, &_3
#define ABC_SET_C_N(_1,_2,_3,N,...) ABC_SET_C##N
#define ABC_SET_C(...) (abc_t){ .kind = C, .u.c_ = (abc_t*[]) { \
ABC_SET_C_N(__VA_ARGS__,_3,_2,_1)(__VA_ARGS__) \
} }
const abc_t pre_builds[] = {
ABC_SET_A(10), // pre_builds[0]
ABC_SET_C(ABC_SET_A(8), ABC_SET_B(4)), // pre_builds[1]
ABC_SET_B(23) // pre_builds[2]
};
Personally I don't like writing (abc_t) a compound literal in macro variable initialization. They make somethings like abc_t *arr = (abc_t[]){
ABC_SET_A(8) } impossible. I prefer leaving writing the &(abc_t) if needed to the user, so that others will know what is a pointer and what is not a pointer, so they know when and how the memory is allocated, what is the storage duration of the memory, etc. It also makes the macro easy to work in C++ and C99. Like this:
#define ABC_SET_A(n) { .kind = A, .u.a_ = n }
#define ABC_SET_B(n) { .kind = B, .u.b_ = n }
#define ABC_SET_C(...) { .kind = C, .u.c_ = __VA_ARGS__ }
const abc_t pre_builds[] = {
ABC_SET_A(10), // pre_builds[0]
ABC_SET_C((abc_t*[]){ &(abc_t)ABC_SET_A(8), &(abc_t)ABC_SET_B(4) }), // pre_builds[1]
ABC_SET_B(23) // pre_builds[2]
};
// it also allows for something like the following naturally to work:
abc_t *make_me_visible_in_debugger[] = {
&(abc_t)ABC_SET_A(8),
&(abc_t)ABC_SET_B(4)
};
const abc_t pre_builds2[] = {
ABC_SET_A(10), // pre_builds[0]
ABC_SET_C(make_me_visible_in_debugger), // pre_builds[1]
ABC_SET_B(23) // pre_builds[2]
};
I have found a lot of questions with this error (initializer element is not constant) but I don't know how to adapt the answers in my code.
(I'm new in C)
I have an error with this part:
#include <mach/i2c.h>
#include <mach/irqs-sun7i.h>
/*
* /////////// from mach/i2c.h //////////
struct sun7i_i2c_platform_data {
int bus_num;
unsigned int frequency;
};
*/
static struct sun7i_i2c_platform_data sun7i_i2c_platform_data = {
.bus_num = 1,
.frequency = 100*1000,
};
static struct mpu_platform_data gyro_platform_data = {
.int_config = 0x10,
.level_shifter = 0,
.orientation = { -1, 0, 0,
0, 1, 0,
0, 0, -1 },
.sec_slave_type = SECONDARY_SLAVE_TYPE_COMPASS,
.sec_slave_id = COMPASS_ID_AK8972,
.secondary_i2c_addr = 0x0E
};
/*
* /////////// from mach/i2c.h //////////
*
* struct i2c_board_info {
char type[I2C_NAME_SIZE];
unsigned short flags;
unsigned short addr;
void *platform_data;
struct dev_archdata *archdata;
struct device_node *of_node;
int irq;
};*/
static struct i2c_board_info __initdata sun7i_i2c_platform_device[] = {
{
I2C_BOARD_INFO("mpu6050", 0x68),
.platform_data = &gyro_platform_data,
.archdata = sun7i_i2c_platform_data,
},
};
/*
// ORIGINAL //
static struct i2c_board_info __initdata single_chip_board_info[] = {
{
I2C_BOARD_INFO("mpu6050", 0x68),
.irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
.platform_data = &gyro_platform_data,
},
};
*/
static void __init sun7i_i2c_init(void)
{
i2c_register_board_info(2, sun7i_i2c_platform_device,
ARRAY_SIZE(sun7i_i2c_platform_device));
}
My problem come from .archdata init:
c:160:17: error: initializer element is not constant
I have tried with
.archdata = &sun7i_i2c_platform_data,
but in this case I have a warning and the line is ignored:
warning: initialization from incompatible pointer type [enabled by default]
So, how to call properly my fonction ?
Thanks
In chasing down a very opaque bug, I have been trying to compile with no warnings or errors. This part of my code worked fine, but gcc complains about the braces--it says there are braces missing and extra braces. I usually initialise a bit more sloppily but here I'm being as pedantic as possible with braces for each logical level of inclusion. The only struct I really care about initialising is the last one, the Ccfg. I thought I'd build up to it gradually as it contains nested other structs, but apparently even the ones preceding it are mis-initialized according to gcc.
Here's the code:
#define max_nodes 24
struct Cseg
{
int begin;
int arc;
int end;
};
struct Node
{
struct Cseg exit[4];
};
struct Core
{
int num_circles;
int num_nodes;
struct Node node[max_nodes];
};
struct Ccfg
{
struct Core core;
int dummy1;
int dummy2;
};
int main(void)
{
struct Cseg A = {0,1,2};
struct Node B =
{
{0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1}
};
struct Node C =
{
{0,1,2}, {1,3,0}
};
struct Core D =
{4, 4,
{
{ {0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1} },
{ {1,3,0}, {2,1,0}, {3,-2,1}, {2,-1,0} },
{ {3,1,2}, {0,1,2}, {1,-3,0}, {2,-3,1} }
}
};
struct Ccfg E =
{
{2, 2,
{
{ {0,1,1}, {0,2,1} },
{ {1,2,0}, {1,1,0} }
}
}
};
return 0;
}
Some of the initialisations are incomplete; that is deliberate. My real ccfg struct has many more fields but I've simplified it for this post. If someone could let me know what I'm doing wrong I'd appreciate it a lot. Thanks!
EDIT: in my working code, the initialiser for struct Ccfg E omits the innermost braces, and works fine (but gcc still warns me about it). I added them into this test because they seemed logically appropriate, but they actually generate an error--which I don't understand.
You are missing braces in some places. Specifically, if you have an array of structs, the entire array needs to be brace-wrapped; you were just wrapping each struct entry. I just added braces as needed and it works fine now. http://ideone.com/fork/HqxB9R
#define max_nodes 24
struct Cseg
{
int begin;
int arc;
int end;
};
struct Node
{
struct Cseg ex[4];
};
struct Core
{
int num_circles;
int num_nodes;
struct Node node[max_nodes];
};
struct Ccfg
{
struct Core core;
int dummy1;
int dummy2;
};
int main(void)
{
struct Cseg A = {0,1,2};
struct Node B =
{
{ {0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1} }
};
struct Node C =
{
{ {0,1,2}, {1,3,0} }
};
struct Core D =
{4, 4,
{
{ { {0,1,2}, {1,3,0}, {2,-1,3}, {0,-2,1} } },
{ { {1,3,0}, {2,1,0}, {3,-2,1}, {2,-1,0} } },
{ { {3,1,2}, {0,1,2}, {1,-3,0}, {2,-3,1} } }
}
};
struct Ccfg E =
{
{2, 2,
{
{ { {0,1,1}, {0,2,1} } },
{ { {1,2,0}, {1,1,0} } }
}
}
};
return 0;
}
struct A{
int a; int b;
};
static const struct A a = {.a1 = 1, .a2 = 42};
struct B{
struct A[666][510]
};
static const struct B b;
I would like to initialize b with copies of a. However, I cannot touch static const things with memcpy(). And I need b to be static const, because that way it gets put into flash and not ram memory.
How do I make this work. The compiler is arm-none-eabi-gcc with -std=c89, I think.
You can try this, though it works specifically for the dimensions that you specify (666 x 510):
#define X001 {1,42}
#define X002 X001,X001
#define X004 X002,X002
#define X008 X004,X004
#define X016 X008,X008
#define X032 X016,X016
#define X064 X032,X032
#define X128 X064,X064
#define X256 X128,X128
#define Y001 {X256,X128,X064,X032,X016,X008,X004,X002}
#define Y002 Y001,Y001
#define Y004 Y002,Y002
#define Y008 Y004,Y004
#define Y016 Y008,Y008
#define Y032 Y016,Y016
#define Y064 Y032,Y032
#define Y128 Y064,Y064
#define Y256 Y128,Y128
#define Y512 Y256,Y256
static const struct A a = X001;
static const struct B b = {{Y512,Y128,Y016,Y008,Y002}};
I recommend that you put these arrays in a separate module in order to achieve encapsulation. Then inside that module you do not need to make B a const but make it static instead.
Any access to this data must be done via getters and setters like this:
mydata.h
#define BA_SIZE 666
struct A{
int a; int b;
};
struct B{
struct A stuff[BA_SIZE];
};
void init(void);
struct A * getB(unsigned int i);
void setB(unsigned int i, struct A element);
mydata.c:
#include "mydata.h"
static const struct A a = {.a = 1, .b = 42};
static struct B b;
void init(void)
{
int i;
for(i=0; i<BA_SIZE; i++) {
b.stuff[i] = a;
}
}
struct A * getB(unsigned int i)
{
return(&b.stuff[i]);
}
void setB(unsigned int i, struct A element)
{
if (i > BA_SIZE) { return; }
b.stuff[i].a = element.a;
b.stuff[i].b = element.b;
}
main.c:
#include <stdio.h>
#include "mydata.h"
int main(void)
{
init();
unsigned int num=1;
struct A * something = getB(num);
printf("element [%u] a=%i b=%i \n", num, something->a, something->b);
return(0);
}
On linux this complies with gcc -std=c89 (don't know about arm cross compiler)
typedef struct A{
int a; int b;
} TA;
typedef struct ARR3 {
TA a[3];
} TARR3;
typedef struct ARR33 {
TARR3 b[3];
} TARR33;
static const TA a = {.a = 1, .b = 42};
TARR33 aa = {
.b[0] = { .a[0] = {.a = 1, .b = 1}, .a[1] = {.a = 2, .b = 2}, .a[2] = {.a = 3, .b = 3} },
.b[1] = { .a[0] = {.a = 4, .b = 4}, .a[1] = {.a = 5, .b = 5}, .a[2] = {.a = 1, .b = 2} },
.b[2] = { .a[0] = {.a = 1, .b = 1}, .a[1] = {.a = 1, .b = 2}, .a[2] = {.a = 1, .b = 2} }
};
main()
{
return 0;
}
The following code gives me this warning:
tag_info.h:17: warning: missing braces around initializer
tag_info.h:17: warning: (near initialization for âtag_list_data[0].subtagsâ)
I have tried alot of things but nothing seems to be working. Can anyone please suggest something
typedef struct Attr{
char attr_name[64];
value_type_t value;
int mandatory;
}Attr_t;
typedef struct Tags {
unsigned int tag_id;
Attr_t *attr_list;
char *tag_name;
int tag_type;
int subtags[html_subtag_num];
}Tags_t;
Tags_t tag_list_data[150] = {
#include "tag_info.h"
{0,0,0,0,0}
};
where the "tag_info.h" contains :
#if defined(TAG_DEFINE)
#undef TAG_DEFINE
#else
#define TAG_DEFINE(a,b,c,...) {.tag_id=a, .tag_name=#b, .tag_type=c, ##__VA_ARGS__}
#endif
TAG_DEFINE(0,TAG_NONE,0,0),
TAG_DEFINE(1,!--,0,0),
TAG_DEFINE(2,!doctype,0,0),
TAG_DEFINE(3,a, 1, 1, 117, 59,11,118,92,100),
You are initializing subtags as if it were multiple members of the Tags struct:
typedef struct Tags {
...
int subtags_0;
int subtags_1;
int subtags_2;
} Tags_t;
Tags_t t = { ..., 0, 1, 2 };
But it is an array. Thus you should initialize it as a single entity.
typedef struct Tags {
...
int subtags[html_subtag_num];
} Tags_t;
Tags_t t = { .tag_id = 0, ..., { 0, 1, 2 } };
// or
Tags_t t = { .tag_id = 0, ..., .subtags = { 0, 1, 2 } };
Also, you don't need to use concatenation (##)
#define TAG_DEFINE(a,b,c,...) { ..., ## __VA_ARGS__}
In the end, it should look like
#define TAG_DEFINE(a,b,c,...) { ..., .subtags = { __VA_ARGS__ } }
...
Tags_t tag_list_data[150] = {
...
{ 0,0,0,0,{0}}
}
instead of
#define TAG_DEFINE(a,b,c,...) { ..., ##__VA_ARGS__}
...
Tags_t tag_list_data[150] = {
...
{ 0,0,0,0,0 }
}