manage similar structs, one with arrays, the other with pointers - c

I have some structs containing arrays
struct mystruct_withArrays {
int foo;
int bar[MaxN];
int baz[MaxM];
}
and their equivalent with pointers
struct mystruct_withPointers {
int foo;
int *bar;
int *baz;
}
and I want to avoid the double definition. This is I want to make something as a template
#define myStruct(M,N)
...
such that myStruct(MaxM,MaxN) produces the array struct and myStruct(,) produces the struct with pointers.
Moreover, of course I want to do the same technique for multiple structs and to have automatic mapping from arrays to pointers. A final use case could be as follow
#include "mystructs.h"
//globals, for huge space usage
struct myStructA(1000,10000) hugeA;
struct myStructB(1024*1024) * hugeB;
void main(){
struct myStructA(,) smallA;
struct myStructB() smallB;
mapStruct(hugeA,smallA) //this is a macro
mapStruct(hugeB,smallB) //this is a macro
doSomething(smallA);
doSomethingMore(smallA,smallB);
doSomethingDetailed(smallB.qux);
}
where mapStruct(hugeA, smallA) is the obvious mapping smallA.bar = hugeA.bar, etc. The expanded code would be:
struct myStructA(1000,10000) hugeA;
struct myStructB(1024*1024) hugeB;
struct mystructA_withArrays {
int foo;
int bar[1000];
int baz[10000];
} hugeA;
struct mystructB_withArrays * {
int qux[1048576];
int quux[1048576];
} hugeB;
void main(){
struct mystructA_withPointers {
int foo;
int * bar;
int * baz;
} smallA;
struct mystructB_withArrays {
int * qux;
int * quxx;
} smallB;
smallA.bar=hugeA.bar;
smallA.baz=hugeA.baz;
smallB.qux=hugeB.qux;
smallB.quxx=hugeB.quxx;
doSomething(smallA);
doSomethingMore(smallA,smallB);
doSomethingDetailed(smallB.qux);
}
As you can see, the general idea is that some variables are allocated outside of the stack, but still without using malloc, just declaring them as globals. Even in some use case they are external globals from a linked shared object.
EDIT:
about memory performance, it is not easy to ascertain if malloc structs are better or worse than global struct. It depends also on the flag -mcmodel of the compiler

The sensible KISS solution seems to be this:
struct mystruct {
int foo;
int *bar;
int *baz;
};
struct mystruct array =
{
.bar = (int[ 1000]){0},
.baz = (int[10000]){0},
};
struct mystruct pointers;
Now the interface of this struct is the same no matter how data was allocated and "array structs" are 100% compatible with "pointer structs". If declared at file scope, the allocation of the compound literals will end up in .bss, same deal as in your pseudo code.

A possible solution to create several similar structures might be the use of an X macro.
(Unlike the Wikipedia page, I pass the macro X as an argument instead of redefining the macro.)
I edited the code a bit to add the assignments of the arrays to the corresponding pointers. I used variadic macros to allow omitting the variable names in the argument list. This is to show the concept, there may be room for improvement.
Example file macro.c
#define LIST_OF_ARRAY_FIELDS_1(X, ...) \
X(int, bar, MaxN, __VA_ARGS__) \
X(int, baz, MaxM, __VA_ARGS__)
#define LIST_OF_ARRAY_FIELDS_2(X, ...) \
X(char, bla1, MaxK, __VA_ARGS__) \
X(char, bla2, MaxL, __VA_ARGS__)
#define CREATE_ARRAY_FIELD(type, name, size, ...) \
type name[size];
#define CREATE_POINTER_FIELD(type, name, size, ...) \
type *name;
struct mystruct_withArrays {
int foo;
LIST_OF_ARRAY_FIELDS_1(CREATE_ARRAY_FIELD)
}
struct mystruct_withPointers {
int foo;
LIST_OF_ARRAY_FIELDS_1(CREATE_POINTER_FIELD)
}
struct otherstruct_withArrays {
int foo;
LIST_OF_ARRAY_FIELDS_2(CREATE_ARRAY_FIELD)
}
struct otherstruct_withPointers {
int foo;
LIST_OF_ARRAY_FIELDS_2(CREATE_POINTER_FIELD)
}
mystruct_withArrays hugeA;
mystruct_withPointers smallA;
otherstruct_withArrays hugeB;
otherstruct_withPointers smallB;
#define ASSIGN_POINTERS(type, name, size, dest, src) \
dest.name = src.name;
LIST_OF_ARRAY_FIELDS_1(ASSIGN_POINTERS, smallA, hugeA)
LIST_OF_ARRAY_FIELDS_2(ASSIGN_POINTERS, smallB, hugeB)
Result:
$ gcc -E macro.c
# 1 "macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "macro.c"
# 15 "macro.c"
struct mystruct_withArrays {
int foo;
int bar[MaxN]; int baz[MaxM];
}
struct mystruct_withPointers {
int foo;
int *bar; int *baz;
}
struct otherstruct_withArrays {
int foo;
char bla1[MaxK]; char bla2[MaxL];
}
struct otherstruct_withPointers {
int foo;
char *bla1; char *bla2;
}
mystruct_withArrays hugeA;
mystruct_withPointers smallA;
otherstruct_withArrays hugeB;
otherstruct_withPointers smallB;
smallA.bar = hugeA.bar; smallA.baz = hugeA.baz;
smallB.bla1 = hugeB.bla1; smallB.bla2 = hugeB.bla2;

Related

How do I make a C macro expand to a struct and function using this method

I want to have a macro
#define MY_STRUCT( /* ... /*) /* ... */
That I want to call this way
MY_STRUCT(point, double x, int y);
Which expands to this
typedef struct {
double x;
int y;
} point;
void init_point(point *p) {
p->x = load_double_from_somewhere();
p->y = load_int_from_somewhere();
}
The macro should be able to handle any number of parameters I give it. I'm trying to generate data bindings for model objects automatically through macros for I've been writing mapping functions by hand and it's tiresome and repetitive (xml to C struct).
I know it's possible but I can't figure out how.
Note: I'm only addressing the question of how to write the struct definition. I don't see a way to get the preprocessor to automatically generate serialisation and deserialisation code, for a couple of reasons. First, it's not possible to extract a token --the member name-- from a macro argument, even if you could know which token to extract. Second, you could use C11's _Generic feature to create calls to pre-defined type-specific serialisation/deserialisation functions. But the _Generic call needs a complete list of possibilites, so it's not going to be possible to incrementally build up the possibilities. I think you'll find that existing systems which autogenerate serialisation/deserialisation code depend on external code generators. That's a much more flexible (and probably easier) strategy.
So, back to autogenerating struct declarations. As has been mentioned, this is really only possible if you generate N macros, one for every number of arguments. And you also need a way to compute N, which might require more automatically-generated macros. All in all, it's a lot easier to use a framework like Jens Gustedt's P99.
Here's a highly simplified illustration of how to do it, with a small limit of fields because the patterns are obvious.
We start with a macro which will compute the number of arguments in a variadic call. Note that this will note correctly return 0 if there are no variadic arguments. A robust solution, like P99, would handle that correctly. But in this case, it doesn't matter because a struct with no members is not allowed by C, so we know there must be at least one argument. (That wouldn't be true in C++.)
#define ARG9_(a1, a2, a3, a4, a5, a6, a7, a8, a9, ...) a9
#define NARGS(...) ARG9_(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
Now, we need eight macros which construct the members. All they have to do is insert semicolons between the arguments, so it's not very challenging:
#define S8_(first, ...) first; S7_(__VA_ARGS__)
#define S7_(first, ...) first; S6_(__VA_ARGS__)
#define S6_(first, ...) first; S5_(__VA_ARGS__)
#define S5_(first, ...) first; S4_(__VA_ARGS__)
#define S4_(first, ...) first; S3_(__VA_ARGS__)
#define S3_(first, ...) first; S2_(__VA_ARGS__)
#define S2_(first, ...) first; S1_(__VA_ARGS__)
#define S1_(first) first;
Finally, we need to put all that together. To do so, we're going to need a macro which can concatenate up a macro name:
#define PASTE3(a, b, c) PASTE3_(a, b, c)
#define PASTE3_(a, b, c) a ## b ## c
Finally, the macro which creates the struct
#define MY_STRUCT(name, ...) \
typedef struct name name; \
struct name { \
PASTE3(S, NARGS(__VA_ARGS__), _)(__VA_ARGS__) \
};
And now we can give it all a try:
MY_STRUCT(s1, int a);
MY_STRUCT(s2, int a, double b);
MY_STRUCT(s3, const char* s, int t[17], double sum);
MY_STRUCT(s4, char a, char b, char c, char d);
MY_STRUCT(s5, char a, char b, char c, char d, char e);
MY_STRUCT(s6, char a, char b, char c, char d, char e, char f);
MY_STRUCT(s7, char a, char b, char c, char d, char e, char f, char g);
MY_STRUCT(s8, char a, char b, char c, char d, char e, char f, char g, short h);
Here's what gcc -E produces, given all of the above: (Note: I can't comment on whether this works on various versions of MSVC. But it's all standard C99.)
# 1 "nargs.h"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "nargs.h"
# 22 "nargs.h"
typedef struct s1 s1; struct s1 { int a; };
typedef struct s2 s2; struct s2 { int a; double b; };
typedef struct s3 s3; struct s3 { const char* s; int t[17]; double sum; };
typedef struct s4 s4; struct s4 { char a; char b; char c; char d; };
typedef struct s5 s5; struct s5 { char a; char b; char c; char d; char e; };
typedef struct s6 s6; struct s6 { char a; char b; char c; char d; char e; char f; };
typedef struct s7 s7; struct s7 { char a; char b; char c; char d; char e; char f; char g; };
typedef struct s8 s8; struct s8 { char a; char b; char c; char d; char e; char f; char g; short h; };
I do not know what you need it for, but ...
#define x(a,b,c) struct a {b;c;}
x(mystr, int m, double n);
and the result is:
struct mystr {int m;double n;};
or
#define x(a,b,c) typedef struct {b;c;} a
x(mystr, int m, double n);
and the result
typedef struct {int m;double n;} mystr;
I'm not sure if it's possible to extract x from double x (unless you know all possible types your variables can have).
Also, iterating over comma-separated lists using preprocessor requires writing boilerplate macros (O(n) of them, I think). Boost.Preprocessor might help with that, but you can completely avoid boilerplate if you use a different syntax:
MY_STRUCT(point, (double,x)(double,y))
Implementation:
#define MY_STRUCT(name, seq) \
typedef struct { \
MY_STRUCT_impl_end(MY_STRUCT_impl_decl_loop_a seq) \
} name; \
void init_point(name *p) { \
MY_STRUCT_impl_end(MY_STRUCT_impl_load_loop_a seq) \
}
#define MY_STRUCT_impl_end(...) MY_STRUCT_impl_end_(__VA_ARGS__)
#define MY_STRUCT_impl_end_(...) __VA_ARGS__##_end
#define MY_STRUCT_impl_decl_loop(type, name) type name;
#define MY_STRUCT_impl_decl_loop_a(...) MY_STRUCT_impl_decl_loop(__VA_ARGS__) MY_STRUCT_impl_decl_loop_b
#define MY_STRUCT_impl_decl_loop_b(...) MY_STRUCT_impl_decl_loop(__VA_ARGS__) MY_STRUCT_impl_decl_loop_a
#define MY_STRUCT_impl_decl_loop_a_end
#define MY_STRUCT_impl_decl_loop_b_end
#define MY_STRUCT_impl_load_loop(type, name) p->name = load_##name##_from_somewhere();
#define MY_STRUCT_impl_load_loop_a(...) MY_STRUCT_impl_load_loop(__VA_ARGS__) MY_STRUCT_impl_load_loop_b
#define MY_STRUCT_impl_load_loop_b(...) MY_STRUCT_impl_load_loop(__VA_ARGS__) MY_STRUCT_impl_load_loop_a
#define MY_STRUCT_impl_load_loop_a_end
#define MY_STRUCT_impl_load_loop_b_end
If you want to autogenerate source code, the preprocessor is the worst tool you can get.
And you absolutely cannot create any macro to generate a struct with any number of fields; the C preprocessor does not support loops or recursion.
But if a maximum of 8 fields/arguments are enough, though NON-STANDARD, this will do in gcc and clang:
#define MY_STRUCT(name, ...) struct name { C2SC(__VA_ARGS__,,,,,,,,,) }
#define C2SC(a, b, c, d, e, f, g, h, ...) a; b; c; d; e; f; g; h;
MY_STRUCT(foo, int bar, int baz, void *quux, void *xuq, char sq[12]);
This deliberately creates a struct name { ... }, not a typedef struct { ... } name as in the OP: It's already obtuse enough even without a MY_STRUCT macro which actually generates a typedef.

Plain "C" static initializer macro with variable length tail.

I have a struct defined as:
typedef struct coro_context {
int id;
jmp_buf env;
list_head list;
jmp_buf waiter;
long timeout;
void *private;
char stack[0];
} coro_context;
which I need to initialize with three values
id = 0
private = function pointer
append to end of struct a suitable char array of length size
My current attempt looks like (the "unsigned long" bit is to get the right alignment):
#define CORO_CONTEXT(name,size) \
unsigned long __##name##_ctx[(sizeof(coro_context)+size)/sizeof(unsigned long)]={0};\
coro_context *name##_ctx = (coro_context *)__##name##_ctx
This works, but has two problems (ok, problems are one and a half ;) ):
it is UGLY (half problem).
I see no way to statically initialize private = name.
Note: I insist on "static initialization" because I want to use this in plain "C" (c11 is ok, if required) because I need to use these initialization outside function context.
I'd use a union overlaying the struct coro_context instance with a char buffer:
#include <setjmp.h>
typedef struct coro_context {
int id;
jmp_buf env;
list_head list;
jmp_buf waiter;
long timeout;
void *private;
char stack[]; /*should be [] in C11, [0] is not valid C */
} coro_context;
/*shouldn't start globals with underscore*/
/*shouldn't violate aliasing rules*/
/*C11 compound literals obviate the need for an extra global identifier*/
#define CORO_CONTEXT(name,size) \
coro_context *name##_ctx = &(union { coro_context ctx; char buf[sizeof(coro_context)+size]; }){ .ctx={ .private=&name } }.ctx;
int my_name;
CORO_CONTEXT(my_name,32)
and then take the address of .ctx. That should also get rid off the aliasing issues your solution has.
You'll need to initialize with an address of a global, because the value of a global is not usable in static initializations.
If you want something C99 compatible, you will need the extra identifier, but it shouldn't start with two underscores:
#include <setjmp.h>
typedef struct coro_context {
int id;
jmp_buf env;
list_head list;
jmp_buf waiter;
long timeout;
void *private;
char stack[1]; /*c99 doesn't have flexible array members*/
} coro_context;
#define CORO_CONTEXT(name,size) \
union { coro_context ctx; char buf[sizeof(coro_context)+size]; } name##_ctx__ = { { 0, {0},{0},{0}, 0, &name } }; \
coro_context *name##_ctx = &name##_ctx__.ctx;
int my_name;
CORO_CONTEXT(my_name,32)
First note that the size of the long buffer, may not match what you expect,as it is rounded to floor. for example if core_context size is 10 bytes, and one requested additional size of 3 bytes, and assuming long size is 8 bytes. you get (10+3)/8 = 1, so you allocate 1 long for handling 13 bytes (instead of allocating 2 longs).
so instead of
unsigned long __##name##_ctx[(sizeof(coro_context)+size)/sizeof(unsigned long)]={0};
I think it shall be
unsigned long __##name##_ctx[(sizeof(coro_context)+size+sizeof(unsigned long))/sizeof(unsigned long)]={0};
now regarding the static initialization, I wouldn't use long buffer, but create a new struct with the same first n variables, and with the requested sized buffer at end. this struct can be initialized statically, and the requested pointer will point to it. so the code would look like this:
#define CORO_CONTEXT(name,size,my_private_method) \
typedef struct coro_context##_name {\
int id;\
jmp_buf env;\
list_head list;\
jmp_buf waiter;\
long timeout;\
void *private;\
char stack[0];\
char additional_buffer[size];\
} coro_context##name;\
coro_context##name __name##_ctx = {0,0,0,0,0,my_private_method};\
coro_context *name##_ctx = (coro_context *)&__name##_ctx
for sake of simplicity, you can examine also this code using simplified struct, and using the coro_context struct as "base" of the wrapper struct (i.e. single variable instead of declaring all coro_context variables):
typedef struct coro_context {
int id;
void *private;
} coro_context;
#define DECLARE_CORO_CONTEXT(size,private_method)\
typedef struct wrapper_for_core_context\
{\
coro_context base;\
char buffer[size];\
}wrapper;\
wrapper my_wrapper = { {0, private_method}, 0 };\
coro_context *cc = (coro_context *)&my_wrapper;
//now the using code
DECLARE_CORO_CONTEXT( 20, test_at_avro_bytes_field_all_data_values );

Aliasing struct members

I have a struct that might have 2 or 4 members depending on a preprocessor definition.
struct foo {
int m1;
int m2;
#ifdef MORE_MEMBERS
int m3;
int m4;
#endif
}
I have functions that take foo.m3 and foo.m4 as arguments. Because of that, I get a compilation error when MORE_MEMBERS isn't defined.
I'm trying to avoid adding #ifdef at every function call. Is there some way to make m3 and m4 be aliases/dummies when MORE_MEMBERS isn't defined? I'd like to still keep the struct size equal to sizeof(int) * 2.
I agree with Iharob, it's horrible code. It's not too clear what you're after, but it sounds like you could use a union:
struct foo
{
int a;
int b;
};
union bar
{
struct foo m1m2;
struct foo m3m4;
};
void f(union bar *x)
{
printf("%d", x->m1m2.a);
printf("%d", x->m3m4.b);
}

Allocating memory for structure types in C

Im having an issue in my program where I define a structure type but not a structure variable in a header as such.
typedef struct
{
int a;
int b;
int c;
Token d;
} Foo;
I then want to use this struct foo later on in a .c file that does infix to postfix
#include "header"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
int infix2postfix(char *infix, Arr arr)
{
struct Foo foo;
char szToken[MAX_TOKEN];
Stack stack = newStack();
infix = getToken(infix, szToken, MAX_TOKEN); //provides next token to be scanned by function.
... //push pop using switch case didn't post code for simplicity.
case...
push(stack, *foo.a);
...
case...
pop(stack);
...
goOut(arr, *foo.d); //goOut(function that populates and "arr" Array from printing.
}
So when I compile here I get
error: storage size of ‘foo’ isn’t known struct Foo foo;
I have tried struct Foo *foo = malloc(sizeof foo); to allocate memory but it messes up my push(stack, *foo.a); and goOut(arr, *foo.d); How do I go about fixing this? Do I have to allocate memory in the infix2postfix function first then declare a structure variable?
You defined a type Foo which is a tagless struct type. You could have a separate struct Foo { int anonymous; char name[MAX_NAME]; }; which is wholly unrelated to the type Foo. (It would be very confusing for humans, but the compiler would have no problem.)
In your function, you should write:
int infix2postfix(char *infix, Arr arr)
{
Foo foo;
you have already defined Foo as a typedef struct, so you do not use struct Foo again to declare foo, just use
Foo foo; to declare not struct Foo foo;

Define a struct based on the definition of an existing struct

If I have an arbitrary struct, is there any way that I can use a macro to add a field to that struct?
for example:
struct foo{
int a,
int b
};
MAGIC(foo, newtype, newname);
Which would evaluate to:
struct foo{
int a;
int b;
};
struct magic_foo{
int a;
int b;
newtype newname;
};
I know this is a stretch, but I'm thinking there might be some built in macro that retrieves the definition of a struct from it's name?
Not directly, since the preprocessor is completely unaware of the C syntax (it operates only as a token replacer; introspection for previously declared types is impossible).
Maybe this is a way to go:
#define STRUCT { \
int a; \
int b; \
EXTRA_MEMBER_DECL \
}
#define EXTRA_MEMBER_DECL /* empty */
struct foo STRUCT;
#define EXTRA_MEMBER_DECL newtype newname;
struct bar STRUCT;
Plan B could be using a nested struct:
struct bar {
struct foo;
newtype newmember;
};

Resources