initializing a structure array in c with #define - c

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 }
}

Related

#define nested struct values in c

I am working on C Structures. I want to #define the struct values as follows.
// #define get_x() { .y = { .z = 1, .c = "test" } }; // this is working
// But I want to replace the above line with
#define get_y() { .z = 1, .c = "test" };
#define get_x() { .y = get_y() }; // this gives error
struct :
typedef struct {
int z;
char c[10];
} y_t;
typedef struct {
y_t y;
} x_t;
int main()
{
x_t x = get_x();
printf("c: %s", x.y.c);
return 0;
}
Will you please help me know, How can I do that?
Remove the ;, there is no ; in initialization. Typically, macros are in upper case.
#define GET_Y() { .z = 1, .c = "test" }
#define GET_X() { .y = GET_Y() }

Initialization of flexible array member is not allowed

I found a GNU C documentation on flexible arrays, and they say that you can initialize them like that:
struct foo { int x; int y[]; };
struct bar { struct foo z; };
struct foo a = { 1, { 2, 3, 4 } }; // Valid.
struct bar b = { { 1, { 2, 3, 4 } } }; // Invalid.
struct bar c = { { 1, { } } }; // Valid.
struct foo d[1] = { { 1, { 2, 3, 4 } } }; // Invalid
But when I try to do the first valid case (with struct a), gcc throws error: Initialization of flexible array member is not allowed. So is this deprecated or is there another way to do it without malloc?

How to get the value of enum from a string

code is here!
I tried to get the value of enum value as string from the user input and want to decode the value and print the case according to it, using Switch case but can't decode the exact value.
enum design {E2F = 1, E2, E3, E4, E5}; char *designation[5];
If someone helps I will be happy
Thanks.
An enum maps symbols to numbers. Here are the 3 options we discussed:
If you want to map strings to numbers use a struct:
struct {
const char *design;
int value;
} designs[] = {
{"E2F", 1},
{"E2", 2},
{"E3", 3}
{"E4", 4},
{"E5", 5}
};
If you want the struct defined in terms of the enum. Generate both from the same data (DESIGNS):
#define DESIGNS\
_(E2F, 1)\
_(E2, 2)\
_(E3, 3)\
_(E4, 4)\
_(E5, 5)
#define _(A, B) A = B,
enum {
DESIGNS
};
#undef _
#define _(A, B) { #A, A },
struct {
const char *design;
int value;
} designs[] = {
DESIGNS
};
which the pre-processor would expand to:
enum {
E2F = 1, E2 = 2, E3 = 3, E4 = 4, E5 = 5,
};
struct {
const char *design;
int value;
} designs[] = {
{ "E2F", E2F }, { "E2", E2 }, { "E3", E3 }, { "E4", E4 }, { "E5", E5 },
};
And here is #DavidCRankin's suggestion (if I understood it right) to just store the array to derive the value from the index:
#include <string.h>
int design_to_number(const char *str) {
const char *designs[] = { "E2F", "E2", "E3", "E4", "E5" };
for(int i = 0; i < sizeof(designs) / sizeof(*designs); i++) {
if(!strcmp(designs[i], str)) return i + 1;
}
return -1;
}
C enum values are just named integers. For string conversion, you'll need to roll our own (unlike Java, for example, where enums are more powerful). One way to go about conversion from string to enum is use the library bsearch function:
#include <stdlib.h>
#include <assert.h>
#include <string.h>
enum design {E2F = 1, E2, E3, E4, E5};
struct design_value {
const char *design;
enum design value;
} designs[] = {
{"E2", E2},
{"E2F", E2F},
{"E3", E3},
{"E4", E4},
{"E5", E5},
};
static int design_value_cmp(const void *a, const void *b) {
return strcmp(((struct design_value*) a)->design, ((struct design_value*) b)->design);
}
enum design get_design(char *designation) {
struct design_value key[1] = {{ designation }};
struct design_value *result = (struct design_value*) bsearch(
key,
designs, sizeof designs / sizeof designs[0], sizeof designs[0],
design_value_cmp);
assert(result);
return result->value;
}
// Tiny verifier. Don't use scanf("%s"...) in real code.
#include <stdio.h>
int main(void) {
char buf[100];
scanf("%s", buf);
printf("%d\n", get_design(buf));
return 0;
}
Note bsearch requires that the strings be in alpha order.

How to call `struct dev_archdata' function?

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

How to statically inialize an array of structures?

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&ltBA_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 &gt BA_SIZE) { return; }
b.stuff[i].a = element.a;
b.stuff[i].b = element.b;
}
main.c:
#include &ltstdio.h&gt
#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-&gta, something-&gtb);
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;
}

Resources