the queue.h implemented by Berkeley in their FreeBSD is very useful indeed, now i got a question about the TAILQ_LAST macro, please note the difference i present
original code
#define TAILQ_HEAD(name, type) \
struct name
{ \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_ENTRY(type) \
struct
{ \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
my proposal
#define TAILQ_LAST(head, headname) \
((head)->tqh_last))
my point is that the tqh_last member of headname refers to the address of the tqe_next member of the last TAILQ_ENTRY, which is exactly the address of the last entry in the tailq.
please correct me if i am wrong. thanks in advance.
Just looking at the two definitions, I'd think that
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
will return a type* whereas this
#define TAILQ_LAST(head, headname) \
((head)->tqh_last))
will return a type**, so both are not equivalent.
No, they are not same. please note that tqh_last is addr of last next element, not last element.
If you directly use (head)->tqh_last, then it simply returns NULL.
Then why it is *(((struct headname *)((head)->tqh_last))->tqh_last)
Please look at:
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
} while (0)
(head)->tqh_last = &TAILQ_NEXT((elm), field);
and what we need is &TAILQ_NEXT((elm), field)->field.tqe_prev, according to (elm)->field.tqe_prev = (head)->tqh_last;, then we get
(*(((struct headname *)((head)->tqh_last))->tqh_last))
Related
So I have macro like this:
#define some_macro(param1) \
static some_struct_t struct = \
{ \
.param1 = param1 \
}
When I call this macro from main with direct value:
some_macro(50);
I got an error :
..\..\main.c(185): error: #29: expected an expression
I found 2 ways to solve it, first was to declare const value within main and pass to macro and second to change name of parameter not be the same as in macro.
So it works but I do not what caused error. Any ideas?
struct is a reserved word, you can not use it as a variable name
Change to something like:
#define some_macro(p1) \
static some_struct_t valid_var_name = \
{ \
.param1 = p1 \
}
If you want to use the same name of the member (param1) as the name of your macro parameter you need to stop the expansion (using ##) or you get .50 = 50
#define some_macro(param1) \
static some_struct_t varname = \
{ \
.param##1 = param1 \
}
There are a few issues with it.
some_struct_t struct is wrong. if some_struct_t is a typedef for a struct or a define for one, you need to do some_struct_t myStruct else struct some_struct_t myStruct
Another issue is, in the code your macro generates, you'll have something like the following (assuming the problem above is fixed):
struct some_struct_t myStruct = { .50 = 50 };
I believe you didn't intend to use 50 as an identifier :)
This may be more like what you want:
#define some_macro(key, value) \
struct some_struct_t myStruct = {\
.key = value\
}
Or if you already know which variable you want to set:
#define some_macro(value) \
struct some_struct_t myStruct = {\
.param1 = value\
}
I'm trying to implement a generic stack in C, with the help of a big macro (not the best way, but that's not the point here).
This macro contains functions declarations, structures and functions calls, with a TYPE type that would be replaced by what needed:
#define STACK(TYPE) \
( \
struct stack \
{ \
size_t size; \
struct container *top; \
}; \
\
struct container \
{ \
TYPE data; \
struct container *next; \
}; \
\
struct stack *stack_init(void) \
{ \
struct stack *s = malloc(sizeof (struct stack)); \
if (!s) \
return NULL; \
return s; \
} \
... ...
)
This header file would be called in any .c file with this line
#include "utils_stack.h"
STACK(int)
Thing is, after trying every possible form of syntax gcc told me to try, I can't find a way to get it to work. I tried with parenthesis, brackets, both, none...
The code just simply won't work. Here is the error I get with the above syntax for example:
error: expected identifier or ‘(’ before ‘struct’
While trying to run gcc with the -E flag, I clearly see that TYPE is being replaced by int.
So here is my question, How do I need to write my macro to be able to... use it ?
Thank you in advance
As mentioned in the comment, this should work, just remove the parentheses:
#include <stdio.h>
#include <malloc.h>
#define STACK(TYPE) \
struct stack \
{ \
size_t size; \
struct container *top; \
}; \
\
struct container \
{ \
TYPE data; \
struct container *next; \
}; \
\
struct stack *stack_init(void) \
{ \
struct stack *s = malloc(sizeof (struct stack)); \
if (!s) \
return NULL; \
return s; \
} \
STACK(int)
int main()
{
struct stack *s;
s = stack_init();
// ...
}
Use parentheses if you define function-like macros, like:
#define maxint(a,b) \
({int _a = (a), _b = (b); _a > _b ? _a : _b; })
See gcc statement expresions for details.
LWN gives the following example on RCU:
Subscribing to an RCU-protected hlist is also similar to the circular
list:
1 rcu_read_lock();
2 hlist_for_each_entry_rcu(p, q, head, list) {
3 do_something_with(p->a, p->b, p->c);
4 }
5 rcu_read_unlock();
Quick Quiz 3: Why do we need to pass two pointers into hlist_for_each_entry_rcu() when only one is needed for
list_for_each_entry_rcu()?
Answer: Because in an hlist it is necessary to check for NULL rather than for encountering the head. (Try coding up a single-pointer
hlist_for_each_entry_rcu(). If you come up with a nice solution, it
would be a very good thing!)
I presume it must refer to an old version of hlist_for_each_entry_rcu() since current version (3.13.0) in rculist.h header actually presents the definition of hlist_for_each_entry_rcu taking 3 arguments, therefore eliminating the need for additional 4th pointer and doesn't seem to be very difficult to invent:
#define hlist_for_each_entry_rcu(pos, head, member) \
for (pos = hlist_entry_safe (rcu_dereference_raw(hlist_first_rcu(head)),\
typeof(*(pos)), member); \
pos; \
pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
&(pos)->member)), typeof(*(pos)), member))
Am I missing something or above version given in current rculist.h is such a very good thing?
We can see something subtle is going on in __rcu_dereference_check where additional pointer is created:
#define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*### needed? ###*/
#define rcu_dereference_check(p, c) \
__rcu_dereference_check((p), rcu_read_lock_held() || (c), __rcu)
#define __rcu_dereference_check(p, c, space) \
({ \
typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
rcu_lockdep_assert(c, "suspicious rcu_dereference_check()" \
" usage"); \
rcu_dereference_sparse(p, space); \
smp_read_barrier_depends(); \
((typeof(*p) __force __kernel *)(_________p1)); \
I wondered the same thing! Digging into the source, it seems like the the four argument version was replace by a three argument version somewhere between 3.8 (https://github.com/torvalds/linux/blob/v3.8/include/linux/rculist.h#L457) and 3.9 (https://github.com/torvalds/linux/blob/v3.9/include/linux/rculist.h#L456)
To compare the two macros, here's the older four argument version:
#define hlist_for_each_entry_rcu(tpos, pos, head, member) \
for (pos = rcu_dereference_raw(hlist_first_rcu(head)); \
pos && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
pos = rcu_dereference_raw(hlist_next_rcu(pos)))
And here's the new three-argument version:
#define hlist_for_each_entry_rcu(pos, head, member) \
for (pos = hlist_entry_safe (rcu_dereference_raw(hlist_first_rcu(head)),\
typeof(*(pos)), member); \
pos; \
pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
&(pos)->member)), typeof(*(pos)), member))
So it seems like the key difference is the hlist_entry_safe macro, which is basically ptr? ptr->member : NULL.
This is not obviously possible because hlist_entry_safe is a macro, so ptr might be an expression, and that expression should not be evaluated more than once. Ex, the obvious solution – #define hlist_entry_safe(ptr, member) ((ptr)? (ptr)->member : NULL) – will not work, because (ptr) will be evaluated twice.
Based on this answer, I assume the syntax that's being used in 3.9 – … ({ typeof(ptr) ____ptr = (ptr); … }) – is a GCC-only extension, which might explain why it wasn't possible at the time the article was written.
I'm doing my hw in C right now and we were given the code below in lecture to create generic types. In C++, I know you can achieve this by just using templates. Our instructor wants us to use these (so no void* for now I don't think).
However, I'm confused as to how I can declare this.
typedef struct Cell(x) *List(x);
struct Cell(x) {
x* data;
List(x) next;
};
So, I know whenever the compiler sees
List(x),
it will substitute in struct Cell(x), so I tried doing List(int) a; in main(), but that doesn't work
New versions of C added "type-generic expressions", allowing for example the abs function to do different things with different argument types.
But as far as I know, there are still no generic types. Your choices for implementing collection types:
Give up type-safety, using void*
Type out the collection / container code for each element type.
Use macros to generate the same code as #2.
I suspect you're intended to do #3. Something along the lines of:
#define Cell(x) specialized_##x##_Cell
#define List(x) specialized_##x##_List
#define SINGLY_LINKED_LIST(x) \\
typedef struct Cell(x) *List(x); \\
struct Cell(x) \\
{ \\
x* data; \\
List(x) next; \\
};
and then you can use it like
SINGLY_LINKED_LIST(int)
int main(void)
{
List(int) a;
}
There is a way you can fake templates for generics like containers in C with macros. You must write two macros that generate declarations and the definition of a new struct type and the functions acting on this type.
For example for an (incomplete) list type:
#define DECLARE_LIST(T_Name, T_Tag, T_Type) \
\
typedef struct T_Name##Node T_Name##Node; \
typedef struct T_Name T_Name; \
\
struct T_Name { \
T_Name##Node *head; \
T_Name##Node *tail; \
int count; \
}; \
\
struct T_Name##Node { \
T_Type value; \
T_Name##Node *next; \
}; \
\
int T_Tag##_init(T_Name *ll); \
int T_Tag##_free(T_Name *ll); \
int T_Tag##_add(T_Name *ll, T_Type x);
#define DEFINE_LIST(T_Name, T_Tag, T_Type) \
\
int T_Tag##_init(T_Name *ll) \
{ \
ll->head = ll->tail = NULL; \
ll->count = 0; \
return 0; \
} \
\
int T_Tag##_free(T_Name *ll) \
{ \
while (ll->head) { \
T_Name##Node *next = ll->head->next; \
free(ll->head); \
ll->head = next; \
} \
return 0; \
} \
\
int T_Tag##_add(T_Name *ll, T_Type x) \
{ \
T_Name##Node *nd = malloc(sizeof(*nd)); \
\
if (nd == NULL) return -1; \
nd->next = NULL; \
nd->value = x; \
\
if (ll->head == NULL) { \
ll->head = ll->tail = nd; \
} else { \
ll->tail->next = nd; \
ll->tail = nd; \
} \
ll->count++; \
\
return 0; \
}
#define IMPLEMENT_LIST(T_Name, T_Tag, T_Type) \
DECLARE_LIST(T_Name, T_Tag, T_Type) \
DEFINE_LIST(T_Name, T_Tag, T_Type) \
If you want to declare a new List type, you should DECLARE_LIST in a header and DEFINE_LIST in the C source. If the type is private to the compilation module, you can just place IMPLEMENT_LIST in the C source.
(The macro is incomplete, because it implements only three functions for the type, which are useless on their own. This is just to show the basic workings. You will usually end up with two huge macros.)
You can use the macro like this:
IMPLEMENT_LIST(Intlist, il, int)
IMPLEMENT_LIST(Stringlist, sl, char *)
This creates two new list types, Intlist and Stringlist, together with the according functions, prefixed il_ and sl_, which you can use like other functions:
int main()
{
Intlist il;
Stringlist sl;
il_init(&il);
sl_init(&sl);
il_add(&il, 1);
il_add(&il, 2);
il_add(&il, 5);
sl_add(&sl, "Hello");
sl_add(&sl, "World");
// ... more stuff ...
il_free(&il);
sl_free(&sl);
return 0;
}
This method is type safe: You can't pass a Stringlist to an il function, for example. Because the code consists only of macros, you can implement it in a header file.
There are restrictions, though:
Assignment is via =. That means that the string list for example can't keep a copy in a char array. If the client code copies data, the clean-up code doesn't know about it. You can cater for such cases by specifying copy, comparison, constructor and destructor functions (which can also be macros) as macro arguments, but this will quickly become complicated.
There are "secret" type names involves like the node type in the example above. They must be valid identifiers (as opposed to C++, where the compiler creates mangles names), which might lead to surprising name clashes.
When you use a private implementation, the functions aren't static as they ought to be.
It has the advantage, that Stringlist is a nicer name than std::list<std::string>, though.
My problem is that atoi is converting a string's hexadecimal memory address to decimal, instead of what's contained within the string. It is doing this during a macro. Why is it interpreting struct->member as a pointer, when the macro definition makes it an int? Pseudocode below:
if (struct.member == int)? struct.member = atoi(data) : struct.member = data;
The aim of this section of the program is to retrieve data from a .csv file containing information about a structs attributes. I can take in an "id" and store each cells string into an array of strings (csvRowSplit).
However, I then want to transfer the contents of the array to a structure that contains different data types (a method that I want to use to retrieve players saved attributes, attack methods, shop items etc.). It's easy to hard code:
opponent->att = atoi(csvSplitRow[0]);
opponent->= atoi(csvSplitRow[1]);
opponent->hitpoints = atoi(csvSplitRow[2]);
opponent->description = csvSplitRow[3]);
However this clutters with more struct members and is not very flexible or reproducible.
I have defined a macro to cycle through the elements of a structure, and pair up the csvSplitRow[] to the variables, converting if required with atoi.
#define X_FIELDS \
X(char*, description, "%s") \
X(int, xpreward, "%d") \
X(int, att, "%d") \
/* ... */
X(int, crit, "%d")
typedef struct
{
#define X(type, name, format) type name;
X_FIELDS
#undef
}
void update_opp(char** csvSplitRow, opp* opponent)
{
int i = 0;
#define X(type, name, format) \
if (strcmp(format, "%d") == 0) \ // if an int, convert it
opponent->name = atoi(csvSplitRow[i]); \
else \ // otherwise put it straight in
opponent->name = csvSplitRow[i]; \
i++;
X_FIELDS
#undef X
}
The assignment directly to the string members work (ie. no conversion), but atoi results in a conversion of the hexadecimal memory address to an integer, instead of the string it's pointing to.
// before conversion
csvRowSplit[1] == 0x501150 "20"
// practice
atoi(csvRowSplit[1]) == 20
// after conversion and storing in struct int member
opponent->xpreward = atoi(csvSplitRow[1]);
opponent->xpreward == 5247312 // the decimal equivalent of 0x501150
I don't know what I can do now, other than hard code each time I want to match up a parsed line of csv with a structure. Please help!
EDIT:
I get a compile time error with -Werror:
error: assignment makes integer from pointer without a cast [-Werror]
Error is within the macro of the update_opp function. However, I know it's not a pointer because I defined it to be an int earlier? So why isn't it recognizing that? and I can't cast it, so what can I do?
Your problem is in this code:
#define X(type, name, format) \
if (strcmp(format, "%d") == 0) \ // if an int, convert it
opponent->name = atoi(csvSplitRow[i]); \
else \ // otherwise put it straight in
opponent->name = csvSplitRow[i]; \
i++;
For any given attribute name (att say), you get:
if (strcmp("%d", "%d") == 0)
opponent->att = atoi(csvSplitRow[i]);
else
opponent->att = csvSplitRow[i];
i++;
Except that it is all on one line. But, the key point is that you either assign an int (from atoi()) to a string or you assign a string to an int in every invocation, and one of those two is wrong. The code has to be correct before it is optimized.
How to fix? That's tricky. I think I'd probably use something like this:
#include <stdlib.h>
#define CVT_INT(str) atoi(str)
#define CVT_STR(str) str
#define X_FIELDS \
X(char*, description, "%s", CVT_STR) \
X(int, xpreward, "%d", CVT_INT) \
X(int, att, "%d", CVT_INT) \
/* ... */ \
X(int, crit, "%d", CVT_INT)
typedef struct opp
{
#define X(type, name, format, converter) type name;
X_FIELDS
#undef X
} opp;
extern void update_opp(char** csvSplitRow, opp* opponent);
void update_opp(char** csvSplitRow, opp* opponent)
{
int i = 0;
#define X(type, name, format, converter) \
opponent->name = converter(csvSplitRow[i++]);
X_FIELDS
#undef X
}
This compiles without warnings under very stringent compiler flags:
gcc -pedantic -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -c xm.c
The CVT_INT and CVT_STR macros could be redefined when required to do other things.
An alternative version of the code exploits CVT_INT and CVT_STR (renamed to X_INT and X_STR) more extensively:
#include <stdlib.h>
#define X_FIELDS \
X(X_STR, description) \
X(X_INT, xpreward) \
X(X_INT, att) \
/* ... */ \
X(X_INT, crit)
typedef struct opp
{
#define X_INT char *
#define X_STR int
#define X(code, name) code name;
X_FIELDS
#undef X
#undef X_INT
#undef X_STR
} opp;
extern void update_opp(char** csvSplitRow, opp* opponent);
void update_opp(char** csvSplitRow, opp* opponent)
{
int i = 0;
#define X_INT(str) atoi(str)
#define X_STR(str) str
#define X(converter, name) \
opponent->name = converter(csvSplitRow[i++]);
X_FIELDS
#undef X
#undef X_INT
#undef X_STR
}
I'm not 100% convinced this is better because of the multiple #define and #undef operations, but it is more nearly minimal in some respects (it doesn't need the "%d" vs "%s" fields, for example — at least, not in the code shown).