How to statically inialize an array of structures? - c

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

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

Initialize constant from another constant with some changes

Let's say a have
struct table { int foo, bar, baz; };
static struct table const A = { .foo = 1, .bar = 2, .baz = 3 };
how could I declare B to be the exact same definition of A but with one change?
For instance what I would like to write is something like
static struct table const B = A, { .bar = 42 };
I am looking for a solution, if any, simpler than the following workaround:
#define A_DEFS .foo = 1, .bar = 2, .baz = 3
static struct table const A = { A_DEFS };
#define B_DEFS A_DEFS, .bar = 42
static struct table const B = { B_DEFS };
Try :
static struct table const B = { A.foo, .bar = 42, A.baz };
SparKot's answer let me come to this slightly more convenient solution:
struct table { int foo, bar, baz; };
#define BASE(X) X.foo, X.bar, X.baz
static struct table const A = { .foo = 1, .bar = 2, .baz = 3 };
static struct table const B = { BASE(A), .bar = 42 };
static struct table const C = { BASE(B), .baz = 24 };

Pointer problem using header file with struct/array, resulting in multiple defenitions error (C)

I have a program (knapsack, optimized for returning the highest value solution with the least weight) for which I want to use external files for the typedef and struct data.
But I can't get it working, somewhere I am messing up with the pointers. I get an 'multiple definition' error or when I change it, I get an 'xxx not declared' error...
/tmp/ccMy5Yw0.o:(.data+0x0): multiple definition of `item1'
Any help on pointing out my thinking mistake in greatly appreciated.
(I compiled online # https://www.onlinegdb.com/)
It did work when I had everything in one file, but after splitting it in different files I can't get it working...
main.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "defs.h"
#include "data.c"
item_t *items[ITEMS_SIZE] = { &item1, &item2, &item3, &item4, &item5, &item6, &item7, &item8, &item9, &item10 };
int *knapsack (item_t * items, int n, int w)
{
int h, h_i, h_j, i, j, a, b, *mm, **m, *s;
mm = calloc ((n + 1) * (w + 1), sizeof (int));
m = malloc ((n + 1) * sizeof (int *));
m[0] = mm;
h = m[0][0];
h_i = 0;
h_j = 0;
for (i = 1; i <= n; i++)
{
m[i] = &mm[i * (w + 1)];
for (j = 0; j <= w; j++)
{
if (items[i - 1].weight > j)
{
m[i][j] = m[i - 1][j];
}
else
{
a = m[i - 1][j];
b = m[i - 1][j - items[i - 1].weight] + items[i - 1].value;
m[i][j] = a > b ? a : b;
if (m[i][j] > h)
{
h = m[i][j];
h_i = i;
h_j = j;
}
}
printf ("%d\t%d\t%d\n", h, h_i, h_j);
}
}
s = calloc (n, sizeof (int));
for (i = h_i, j = h_j; i > 0; i--)
{
if (m[i][j] > m[i - 1][j])
{
s[i - 1] = 1;
j -= items[i - 1].weight;
}
}
free (mm);
free (m);
return s;
}
int main ()
{
int i, n, tw = 0, tv = 0, *s;
for (i = 0; i < 10; i++)
{
if (items[i]->SwitchOn)
{
items[i]->value = items[i]->value;
}
else
{
items[i]->value = 0;
}
}
n = sizeof (items) / sizeof (item_t);
s = knapsack (items, n, 690);
for (i = 0; i < n; i++)
{
if (s[i])
{
printf ("%-22s %5d %5d\n", items[i]->name, items[i]->weight,
items[i]->value);
tw += items[i]->weight;
tv += items[i]->value;
}
}
printf ("%-22s %5d %5d\n", "totals:", tw, tv);
return 0;
}
defs.h
#ifndef SYSTEMDEFS_H_INCLUDED
#define SYSTEMDEFS_H_INCLUDED
#define ITEMS_SIZE 10
typedef struct Item
{
char name[40];
int weight;
int value;
bool SwitchOn;
} item_t;
extern item_t item1;
extern item_t item2;
extern item_t item3;
extern item_t item4;
extern item_t item5;
extern item_t item6;
extern item_t item7;
extern item_t item8;
extern item_t item9;
extern item_t item10;
#endif
data.c
#include <stdbool.h>
#include "defs.h"
item_t item1 =
{
.name = "part1",
.weight = 25,
.value = 8,
.SwitchOn = false,
};
item_t item2 =
{
.name = "part2",
.weight = 40,
.value = 2,
.SwitchOn = true,
};
item_t item3 =
{
.name = "part3",
.weight = 60,
.value = 7,
.SwitchOn = false,
};
item_t item4 =
{
.name = "part4",
.weight = 100,
.value = 6,
.SwitchOn = false,
};
item_t item5 =
{
.name = "part5",
.weight = 150,
.value = 2,
.SwitchOn = true,
};
item_t item6 =
{
.name = "part6",
.weight = 380,
.value = 10,
.SwitchOn = true,
};
item_t item7 =
{
.name = "part7",
.weight = 850,
.value = 2,
.SwitchOn = false,
};
item_t item8 =
{
.name = "part8",
.weight = 75,
.value = 15,
.SwitchOn = true,
};
item_t item9 =
{
.name = "part9",
.weight = 800,
.value = 1,
.SwitchOn = false,
};
item_t item10 =
{
.name = "part10",
.weight = 75,
.value = 8,
.SwitchOn = true,
};
As you included data.c in main.c
#include "defs.h"
#include "data.c"
then now the code in data.c is duplicated in two translation units: one with main.c and other with data.c.
Remove this line
#include "data.c"
from main.c.
Also pay attention to thatf you declared an array of the type item_t *[ITEM_SIZE]
item_t *items[ITEMS_SIZE] = { /*...*/ };
So if you will pass it as an argument expression to a function it is implicitly converted to the pointer to its first element of the type item_t **. But you are passing the array to the function knapsack
s = knapsack (items, n, 690);
the first parameter of which has the type item_t *.
int *knapsack (item_t * items, int n, int w)
So the compiler should issue a message that the pointer types are noyt compatible. That is whether the function is declared and defined incorrectly or you are calling it supplying incorrect arguments.

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

initializing a structure array in c with #define

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

Resources