What is the rationale behind using an union in DECLARE_KFIFO - c

I am looking at the <linux/kfifo.h>, specifically the DECLARE_KFIFO macro, and I can't figure out why use an union.
#define DECLARE_KFIFO(name, size) \
union { \
struct kfifo name; \
unsigned char name##kfifo_buffer[size + sizeof(struct kfifo)]; \
}
My questions are as follows:
What is the point of using an union over here ? What design goal does that solve ? Is it for performance reasons ?
How would you even access this anonymous union ? For example this does not work:
#include <stdio.h>
int main()
{
union {
int a;
float b;
};
a = 10;
}
main.c:18:5: error: ‘a’ undeclared (first use in this function)
a = 10;
^
Why declare something that cannot be used ?
How does this work with the INIT_KFIFO macro ? How is able to access the union and what relation does it have with the previous macro ?
If my memory serves me correctly, then in C you can only use one one element in an union. So what is going on here ? It will just use one member from the declared union ?
Note: This code is for the 2.6.33 kernel. I know its old code, but the recent kernel 5.6.12 still uses a union in kfifo, only its a lot more complicated.

The comments to the macro explain almost everything:
/**
* DECLARE_KFIFO - macro to declare a kfifo and the associated buffer
* #name: name of the declared kfifo datatype
* #size: size of the fifo buffer. Must be a power of two.
*
* Note1: the macro can be used inside struct or union declaration
* Note2: the macro creates two objects:
* A kfifo object with the given name and a buffer for the kfifo
* object named name##kfifo_buffer
*/
This macro is used only as a (some other) structure's or union's field. With such usage the macro creates(allocates in the structure or in the union):
a kfifo object which can be accessed as a field with the name name and
a buffer for kfifo.
So, structure declaration like
struct my_struct {
int a;
char b;
DECLARE_KFIFO(my_fifo, 100);
};
gives similar effect as
struct my_struct {
int a;
char b;
// This field may be used for call kfifo functions
struct kfifo my_fifo;
// This field is never used directly.
// Pointer to this buffer is stored in the '.buffer' field of kfifo object.
unsigned char buffer_internal_to_kfifo_implementation[size];
};
It would be more natural for declaring two objects to use a anonymous structure of two fields instead of union:
#define DECLARE_KFIFO(name, size) \
struct { \
struct kfifo name; \
unsigned char name##kfifo_buffer[size]; \
}
It should be exactly anonymous for allow direct access to its name field.
Compared to structure's implementation, actual implementation of DECLARE_KFIFO via anonymous union gives the same "field" name and allocates the same amount of bytes (of number size) for its buffer:
union { \
struct kfifo name; \
unsigned char name##kfifo_buffer[size + sizeof(struct kfifo)]; \
}
It is difficult to say why they choose union instead of struct.
the recent kernel 5.6.12 still uses a union in kfifo, only its a lot more complicated.
Not quite true. The newer kernel versions uses union for absolutely different purposes:
#define __STRUCT_KFIFO_COMMON(datatype, recsize, ptrtype) \
union { \
struct __kfifo kfifo; \
datatype *type; \
const datatype *const_type; \
char (*rectype)[recsize]; \
ptrtype *ptr; \
ptrtype const *ptr_const; \
}
Here kfifo is the only field which is accessed for write/read bytes of data. All other fields are declared just for extract their types using typeof() operator.
So, __STRUCT_KFIFO_COMMON is just a "clever" struct kfifo declaration which knows types of data it contains.
Definition of DECLARE_KFIFO macro
#define DECLARE_KFIFO(fifo, type, size) STRUCT_KFIFO(type, size) fifo
after expanding intermediate macros gives:
#define DECLARE_KFIFO(fifo, type, size) struct { \
__STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
type buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
} fifo
So that time it is a field of the structure type with the given name. Similar to the old definition, this structure contain two fields:
struct kfifo object (its "clever" version) and
a buffer for kfifo.

Related

Create a struct in C Preprocessor

Right now, I am writing a small project in C to test out some serialization techniques.
One way that I am doing this is through the use of unions. Something that I would like to try is creating a union in the C preprocessor that holds a user-defined structure. For example, something like this:
#define create_union(name_of_structure, type_of_structure) \
\
typedef union name_of_structure { \
typeof(type_of_structure) structure; \
char buffer_that_holds_structure[sizeof(type_of_structure)]; \
} name_of_structure;
/* Usage */
struct my_data {
int id;
int other_value;
};
create_union(my_data_t, struct my_data);
/* Data type my_data_t (union my_data_t) now exists */
First of all, is this feasible? If it is, how would I go about doing this? If not, is there an alternative method I can use?
Thanks!
Yes, it's possible, and your code is very close to correct.
I'd drop the semicolon at the end of the macro definition. I'd also drop the use of typeof; it's not portable and it's not needed unless you want to use an expression, rather than a type name, as the first argument to create_union.
Here's how I'd probably define it. (I don't bother with typedefs for struct or union types; I just use the name struct foo or union foo unless the type is intended to be completely opaque. Feel free to use the typedef if you prefer.) (I've also used unsigned char rather than char, since that's how object representations are defined.)
#define CREATE_UNION(new_type, existing_type) \
union new_type { \
existing_type obj; \
unsigned char rep[sizeof(existing_type)]; \
}
And you can then do:
CREATE_UNION(int_wrapper, int);
int_wrapper foo;
Note that what you're defining is a union, not a structure.

Use of macros in array definition in C

I am new to C and using it to program a Nordic nrf52 chip. I believe my problem is a general C one though rather than application.
I am setting up an array of structs using macros predefined in the chip SDK. Using those macros in the array initialisation works, but doing element by element does not.
So, the following works:
nrf_twi_mngr_transfer_t transfers_1[2] = { \
NRF_TWI_MNGR_WRITE(MSBARO5X_0_ADDR , &reg_addr[1], 1, NRF_TWI_MNGR_NO_STOP), \
NRF_TWI_MNGR_READ (MSBARO5X_0_ADDR , &p_buffer[0], sizeof(p_buffer), 0)
};
Where:
typedef struct {
uint8_t * p_data; ///< Pointer to the buffer holding the data.
uint8_t length; ///< Number of bytes to transfer.
uint8_t operation; ///< Device address combined with transfer direction.
uint8_t flags; ///< Transfer flags (see #ref NRF_TWI_MNGR_NO_STOP).
} nrf_twi_mngr_transfer_t;
NRF_TWI_WRITE and _READ are macros that use further macros, for example:
#define NRF_TWI_MNGR_WRITE(address, p_data, length, flags) \
NRF_TWI_MNGR_TRANSFER(NRF_TWI_MNGR_WRITE_OP(address), p_data, length, flags)
which uses
#define NRF_TWI_MNGR_WRITE_OP(address) (((address) << 1) | 0)
and
#define NRF_TWI_MNGR_TRANSFER(_operation, _p_data, _length, _flags) \
{ \
.p_data = (uint8_t *)(_p_data), \
.length = _length, \
.operation = _operation, \
.flags = _flags \
}
What I want to do is change individual items in this array, for example:
transfers_1[0] = NRF_TWI_MNGR_WRITE(MSBARO5X_0_ADDR , &reg_addr[1], 1, NRF_TWI_MNGR_NO_STOP);
However when I do that, I get the error "expected an expression".
MSBARO5X_0_ADDR is also defined in a define statement:
#define MSBARO5X_0_ADDR 0x76
If I replace this in any of the above code with a variable, I get the same "expected an expression" error. I suspect the two problems I have are due to the same lack of understanding on my part. SO forgive me for combining the two in a single post.
So the questions are:
-Why am I getting this error?
-Is it possible to change individual items in my array, and if so how?
-Is it possible to use a variable in place of the MSBARO5X_ADDR, and if so how?
Many thanks!
Ultimately, the macro expands into a brace enclosed initializer. Such a thing is not an expression, so it cannot be used as the right hand side of plain assignment (assignment and initialization are different things). It will work as part of a larger initializer, but not the way you try to use it unmodified.
But all is not lost. The syntax of the initializer implies c99 support. So we can use a trick. Structure objects can be assigned to eachother. So we need only obtain an object from somewhere. We can use a compound literal in order to create said object:
transfers_1[0] = (nrf_twi_mngr_transfer_t)NRF_TWI_MNGR_WRITE(/*Your arguments*/);
If you define the value of a structure the moment you declare it, the compiler will infer the type of the structure from the declaration. So this here will compile:
struct coordinates {
int x;
int y;
};
struct coordinates origin = { 10, 20 }; // This is OK
But if you assign a value to a previously declared variable, the compiler cannot infer its type. This code won't compile:
struct coordinates origin;
origin = { 10, 20 }; // ERROR! The type of the rvalue is unknown!
The type is unknown, because two structures are not equivalent in C just because they have the same members. E.g. this is legal in C:
struct coordinates {
int x;
int y;
};
struct dayOfYear {
int day;
int month;
};
Now what would { 5, 8 } be? The coordinates (5/8) or the 5th of August? It could be both. All that he compiler knows is that it is a struct of type { int, int }. Yet this does not define a type in C. The following is possible in some languages but it's not possible in C:
struct dayOfYear date = { 2, 3 };
struct coordinates cords = date; // ERROR!
Despite the fact that both structures are of type { int, int }, for the compiler struct dayOfYear and struct coordinates are two completely distinct and unrelated data types.
If you want to declare a hardcoded struct value, you need to tell the compiler what kind of struct that is:
struct coordinates origin;
origin = (struct coordinates){ 10, 20 }; // This is OK
Your NRF_TWI_MNGR_TRANSFER defines a hardcoded struct but only when you use that in a definition the compiler knows the type. If you try to use it as an assignment, you need to cast to the correct type.
transfers_1[0] = (nrf_twi_mngr_transfer_t)NRF_TWI_MNGR_WRITE(MSBARO5X_0_ADDR , &reg_addr[1], 1, NRF_TWI_MNGR_NO_STOP);
Which is not really a cast, even though it has the same syntax. In fact this is just telling the compiler how to interpret the following data.

Compile time check polymorphic types in C?

Polymorphic structs are quite common in C but often involve explicit casts which allow for accidentally casting incompatible structs.
struct ID {
char name[32];
};
struct IntID {
struct ID id_base;
int value;
}
struct FloatID {
struct ID id_base;
float value;
}
void id_name_set(ID *id, const char *name)
{
strlcpy(id->name, name, sizeof(id->name));
}
/* macro that happens to use 'id_name_set', this is a bit contrived */
#define ID_NAME_SET_AND_VALUE(id, name, val) \
do { \
id_name_set((ID *)id, name); \
id->value = val; \
} while(0)
void func(void)
{
struct { int value; } not_an_id;
/* this can crash because NotID doesn't have an ID as its first member */
ID_NAME_SET_AND_VALUE(not_an_id, "name", 10);
}
The issue here is we can't type check the id argument in the macro against a single type, since it could be an ID or any struct with an ID as its first member.
A lot of code I've seen simply casts to the struct all over the place, but it seems it is possible to have a more reliable method.
Is there a way to check at compile time?
Note, for the purpose of this question, we can assume all structs use the same member name for the struct they inherit from.
Note, I was hoping to be able to use something like this...
# define CHECK_TYPE_POLYMORPHIC(val, member, struct_name) \
(void)(_Generic((*(val)), \
/* base-struct */ struct_name: 0, \
/* sub-struct */ default: (_Generic(((val)->member), struct_name: 0))))
/* --- snip --- */
/* check that `var` is an `ID`, or `var->id_base` is */
CHECK_TYPE_POLYMORPHIC(var, id_base, ID);
...but this fails for ID types in the default case - because they have no id member.
So far the only way I found to do this is to type-check against a complete list of all structs, which isn't ideal in some cases (may be many — or defined locally, therefore not known to the macro, see: Compile time check against multiple types in C?).
You shouldn't use casts. A cast supposes that you know what you are doing and in the worst case leads to undefined behavior. You'd have to rely on the fact that the types that you are interested in all have that struct ID field with the same name.
Then, in the case that you present where you actually have a do-while kind of functional macro, you can easily place an auxiliary variable:
#define ID_NAME_SET_AND_VALUE(id, name, val) \
do { \
ID* _id = &((id)->id_base)); \
id_name_set(_id, (name)); \
_id->value = (val); \
} while(0)
If all goes well, this is a nop, if not it is a constraint violation and aborts compilation.
In a context where you can't place a variable you could use a compound literal, something like
(ID*){ &((id)->id_base)) }
The closest thing in C11 (the latest C standard) for compile-time polymorphism is its
type-generic expressions using the _Generic keyword, but I am not sure it fits your needs.
The GCC compiler also gives you its __builtin_type_compatible_p with which you could build e.g. some macros.
You could also customize GCC with some MELT extensions

Macro to allocate struct on stack with pre-computed member lengths

I have a struct of the form:
typedef struct node {
unsigned int * keys;
unsigned int * branches;
} NODE;
The number of keys and branches is determined at runtime, but is known. It is derived from another struct:
typedef struct tree {
unsigned int num_keys_per_node;
} TREE;
In order to allocate a NODE for this TREE, the manual steps would be:
NODE node;
unsigned int keys[tree->num_keys_per_node];
unsigned int branches[tree->num_keys_per_node + 1];
node.keys = keys;
node.branches = branches;
I need to allocate a lot of these nodes inside tight loops, only temporarily as I traverse a data structure, discarding them quickly as the node traversal continues. I could write a function that returns a pointer and malloc() the keys and branches on the heap and free() them manually, but I'd prefer to use the stack if possible.
Since this initialization logic is going to be repeated in a number of places, how can I define a macro, so that I can effectively do something like:
NODE node = CREATE_NODE_FOR_TREE(tree);
I'm having difficultly seeing a way to do this which will result in the preprocessor giving a valid syntax.
Happy to hear other approaches to dynamic struct allocation on stack memory too.
EDIT | I should never need more than one node in memory at the same time, so I can re-use the one struct repeatedly too.
Try to pass node as argument to the macro like so:
#define CREATE_NODE_FOR_TREE( \
node, \
tree) \
\
unsigned int keys[tree->num_keys_per_node]; \
unsigned int branches[tree->num_keys_per_node + 1]; \
\
node.keys = keys; \
node.branches = branches;
...
NODE node = {0};
CREATE_NODE_FOR_TREE(node, tree);
...
This solution assumes at least c99.
Compound literals can't be VLA and your size parameter is dynamic, so there is no possibility to do that directly with the syntax that you propose. I'd do the following:
#define NODE_ON_STACK(NAME, TREE) \
NODE NAME = { 0 }; \
register size_t NAME ## keys = (TREE)->num_keys_per_node; \
auto unsigned int NAME ## keys[NAME ## keys]; \
auto unsigned int NAME ## branches[NAME ## keys + 1]; \
node.keys = NAME ## keys; \
node.branches = NAME ## branches
This works at any place in function scope where several declarations can be placed. register and auto ensure that it is never used in file scope. The NAME ## keys variable ensures that the TREE argument is only evaluated once. You also could mangle the names of the identifiers that are generated a bit more to avoid conflicts, if you like.
Nitpicks:
always initialize struct variables
your TREE thing got somehow wrong in the question
the & operator in your question was wrong
int as an integer type is almost certainly wrong, things that are counting stuff should be unsigned
unsigned int is also wrong, size_t is usually best for everything
that is supposed to count objects or parts of it.
Ah and the usual warning tag: VLA as auto variables are to be taken carefully because of stackoverflow. But you knew that already, I suppose.
I think that something like the following might work, though I'm not sure if it's the best way to do this:
#define PASTE2(x,y) x##y
#define PASTE(x,y) PASTE2(x,y)
#define CREATE_NODE_FOR_TREE( n, tree) \
NODE n; \
unsigned int PASTE(n,_keys)[(tree)->num_keys_per_node]; \
unsigned int PASTE(n,_branches)[(tree)->num_keys_per_node + 1]; \
n.keys = &PASTE(n,_keys); \
n.branches = &PASTE(n,_branches);
The token pasting is there so that if at some point you needed to use more than one NODE at a time, the 'hidden' keys and branches locals would have their names 'scoped' to the NODE name to avoid a conflict.
To use it, instead of
NODE node = CREATE_NODE_FOR_TREE(tree);
You'd declare and initialize node like so:
CREATE_NODE_FOR_TREE(node, tree);

Is there any way to loop through a struct with elements of different types in C?

my struct is some like this
typedef struct {
type1 thing;
type2 thing2;
...
typeN thingN;
} my_struct
how to enumerate struct childrens in a loop such as while, or for?
I'm not sure what you want to achieve, but you can use X-Macros and have the preprocessor doing the iteration over all the fields of a structure:
//--- first describe the structure, the fields, their types and how to print them
#define X_FIELDS \
X(int, field1, "%d") \
X(int, field2, "%d") \
X(char, field3, "%c") \
X(char *, field4, "%s")
//--- define the structure, the X macro will be expanded once per field
typedef struct {
#define X(type, name, format) type name;
X_FIELDS
#undef X
} mystruct;
void iterate(mystruct *aStruct)
{
//--- "iterate" over all the fields of the structure
#define X(type, name, format) \
printf("mystruct.%s is "format"\n", #name, aStruct->name);
X_FIELDS
#undef X
}
//--- demonstrate
int main(int ac, char**av)
{
mystruct a = { 0, 1, 'a', "hello"};
iterate(&a);
return 0;
}
This will print :
mystruct.field1 is 0
mystruct.field2 is 1
mystruct.field3 is a
mystruct.field4 is hello
You can also add the name of the function to be invoked in the X_FIELDS...
There is no safe way to enumerate a struct's members, unless the exact contents of the struct is known, and even in that case you have to be careful of things like struct alignment/padding.
Depending on your problem, it might be safer to have an array of your struct.
Since you plan to handle them in a loop, I assume the different types can at least be treated alike, or have similar sizes.
If this is the case, your choice will depend on the size of the elements. If they're all the same, you can retrieve a pointer to the structure, cast it to one of your types, and increment it until you 'used up' the whole structure.
PS: Indeed, not a very safe practice. This a situation handled much better with an OO approach, taking advantage of polymorphism. Otherwise, there's no guarantees about alignment as previously mentioned.
There's no way to iterate through struct members in C language, regardless of whether the have the same size/type or different sizes/types.
For the reference, you can loop through struct elements using pointer arithmetic, if they are the same type:
typedef struct numbers{
int a;
int b;
int c;
} numbers;
numbers nums;
nums.a = 42;
nums.b = 99;
nums.c = 23;
int count = sizeof(nums) / sizeof(int); // 3
for(int i=0; i < count; i++){
printf("%d ", *(&nums.a + i) ); // start on the first field's address
}

Resources