I have the follow macro:
#define my_add_property(ret, name, value) \
object tmp; \
tmp = *value; \
add_property(ret, name, &tmp);
Now I use the macro in the follow function:
void func() {
object *ret;
my_add_property(ret, "key", my_func1());
my_add_property(ret, "value", my_func2());
}
It will have make error: tmp is redefined.
So I want to use object tmp##name, but if name is "key", tmp##name will be tmp"key". I should do how write the macro that make tmp##name to tmpkey not tmp"key"? thanks!
You can create a new scope inside your macro, such that tmp is only live for a short amount of time by wrapping the implementation in a do {} while(0), for example:
#define my_add_property(return, name, value) do { \
object tmp; \
tmp = *value; \
add_property(return, name, &tmp); } while(0)
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 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.
I found a header to define hashtable with the following code :
#ifndef HASH_H
#define HASH_H
#define DEFINE_HASHTABLE(name, type, key, h_list, hashfunc)\
\
struct list * hashtable;\
\
static int hashtable_init (size_t size)\
{\
unsigned long i;\
hashtable = (struct list*)malloc(size * sizeof (struct list_head));\
if (!hashtable)\
return -1;\
for (i = 0; i < size; i++)\
INIT_LIST_HEAD(&hashtable[i]);\
return 0;\
}\
\
static inline void hashtable_add(type *elem)\
{\
struct list_head *head = hashtable + hashfunc(elem->key);\
list_add(&elem->h_list, head);\
}\
\
static inline void hashtable_del(type *elem)\
{\
list_del(&elem->h_list);\
}\
\
static inline type * hashtable_find(unsigned long key)\
{\
type *elem;\
struct list_head *head = hashtable + hashfunc(key);\
\
list_for_each_entry(elem, head, h_list){\
if (elem->key == key) \
return elem; \
}\
return NULL;\
}
#endif /* _HASH_H */
I never seen a header file such this one. What is the advantage of this way to write a header (I mean full macro)? Is it about genericity or things like that?
It's a way to try to ensure that all the hash function calls have their inline request granted, i.e. to reduce the number of function calls when doing hash table operations.
It's just an attempt, it can't guarantee that the functions will be inlined, but by making them static the chance at least improves. See this question for lots of discussion about this, in particular #Christoph's answer here.
Note that it will only work once per C file, since there's no "unique" part added to the function names.
If you do:
#include "hash.h"
DEFINE_HASHTABLE(foo, /* rest of arguments */);
DEFINE_HASHTABLE(bar, /* another bunch of args */);
you will get compilation errors, since all the hashtable_ functions will be defined twice. The macro writer could improve this by adding the name to all the things defined (variables and functions) by the set of macros.
I.e. this:
struct list * hashtable;\
\
static int hashtable_init (size_t size)\
should become something like:
static list *hashtable_ ##name;\
\
static int hashtable_ ##name ##_init(size_t size)\
and so on (where name is the first macro argument, i.e. the foo and bar from my example usage above).
I'm trying to work through an issue on a third party library. The issue is the library uses GCC's nested functions buried in a macro, and Clang does not support nested functions and has no plans to do so (cf., Clang Bug 6378 - error: illegal storage class on function).
Here's the macro that's the pain point for me and Clang:
#define RAII_VAR(vartype, varname, initval, dtor) \
/* Prototype needed due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36774 */ \
auto void _dtor_ ## varname (vartype * v); \
void _dtor_ ## varname (vartype * v) { dtor(*v); } \
vartype varname __attribute__((cleanup(_dtor_ ## varname))) = (initval)
And here's how its used (from the code comments):
* void do_stuff(const char *name)
* {
* RAII_VAR(struct mything *, thing, find_mything(name), ao2_cleanup);
* if (!thing) {
* return;
* }
* if (error) {
* return;
* }
* do_stuff_with_thing(thing);
* }
The Clang User Manual states to use C++ and a lambda function to emulate. I'm not sure that's the best strategy, and a C project will likely not accept a C++ patch (they would probably tar and feather me first).
Is there a way to rewrite the macro so that's its (1) more accommodating to Clang, and (2) preserves original function semantics?
Clang doesn't support GCC nested functions, but it does support Objective C-style "blocks", even in C mode:
void f(void * d) {
void (^g)(void *) = ^(void * d){ };
g(d);
}
You need to invoke it with the clang command rather than gcc, and also (?) pass -fblocks -lBlocksRuntime to the compiler.
You can't use a block as a cleanup value directly, since it has to be a function name, so (stealing ideas from here) you need to add a layer of indirection. Define a single function to clean up void blocks, and make your RAII'd variable the block that you want to run at the end of the scope:
typedef void (^cleanup_block)(void);
static inline void do_cleanup(cleanup_block * b) { (*b)(); }
void do_stuff(const char *name) {
cleanup_block __attribute__((cleanup(do_cleanup))) __b = ^{ };
}
Because blocks form closures, you can then place the operations on your variables to cleanup directly inside that block...
void do_stuff(const char *name) {
struct mything * thing;
cleanup_block __attribute__((cleanup(do_cleanup))) __b = ^{ ao2_cleanup(thing); };
}
...and that should run at the end of the scope as before, being invoked by the cleanup on the block. Rearrange the macro and add a __LINE__ so it works with multiple declarations:
#define CAT(A, B) CAT_(A, B)
#define CAT_(A, B) A##B
#define RAII_VAR(vartype, varname, initval, dtor) \
vartype varname = (initval); \
cleanup_block __attribute__((cleanup(do_cleanup))) CAT(__b_, __LINE__) = ^{ dtor(varname); };
void do_stuff(const char *name) {
RAII_VAR(struct mything *, thing, NULL, ao2_cleanup);
...
Something like that, anyway.
I believe you can do this without using a clang-specific version, I'd try something like this (untested, may require a few extra casts):
struct __destructor_data {
void (*func)(void *);
void **data;
}
static inline __destructor(struct __destructor_data *data)
{
data->func(*data->data);
}
#define RAII_VAR(vartype, varname, initval, dtor) \
vartype varname = initval; \
__attribute((cleanup(__destructor))) \
struct __destructor_data __dd ## varname = \
{ dtor, &varname };
In our project we have a gcc-specific _auto_(dtor) macro that precedes the normal variable declaration, e.g.:
_auto_(free) char *str = strdup("hello");
In this case our macro can't add anything after the variable declaration and also doesn't know the name of the variable, so to avoid using gcc-specific nested functions I came up with the following hackish version in case this helps anyone:
static void *__autodestruct_value = NULL;
static void (*__autodestruct_dtor)(void *) = NULL;
static inline void __autodestruct_save_dtor(void **dtor)
{
__autodestruct_dtor = *dtor;
__autodestruct_dtor(__autodestruct_value);
}
static inline void __autodestruct_save_value(void *data)
{
__autodestruct_value = *(void **) data;
}
#define __AUTODESTRUCT(var, func) \
__attribute((cleanup(__autodestruct_save_dtor))) \
void *__dtor ## var = (void (*)(void *))(func); \
__attribute((cleanup(__autodestruct_save_value)))
#define _AUTODESTRUCT(var, func) \
__AUTODESTRUCT(var, func)
#define _auto_(func) \
_AUTODESTRUCT(__COUNTER__, func)
This is hackish because it depends on the order the destructors are called by the compiler being the reverse of the order of the declarations, and it has a few obvious downsides compared to the gcc-specific version but it works with both compilers.
Building on the answers above, here's my hack to allow clang to compile nested procedures written in gcc-extension style. I needed this myself to support a source-to-source translator for an Algol-like language (Imp) which makes heavy use of nested procedures.
#if defined(__clang__)
#define _np(name, args) (^name)args = ^args
#define auto
#elif defined(__GNUC__)
#define _np(name, args) name args
#else
#error Nested functions not supported
#endif
int divide(int a, int b) {
#define replace(args...) _np(replace, (args))
auto int replace(int x, int y, int z) {
#undef replace
if (x == y) return z; else return x;
};
return a / replace(b,0,1);
}
int main(int argc, char **argv) {
int a = 6, b = 0;
fprintf(stderr, "a / b = %d\n", divide(a, b));
return 0;
}
I have the following line of c (carriage returns added for readability - they aren't in the code):
#define i2c_write(slave_addr, reg_addr, len, *data_ptr)
twi_master_write(MPU_TWI, {
.addr = reg_addr,
.addr_length = 1,
.buffer = *data_ptr,
.length = len,
.chip = slave_addr
})
Where twi_master_write() is declared as:
uint32_t twi_master_write(Twi *p_twi, twi_packet_t *p_packet);
and twi_packet_t is declared as:
typedef struct twi_packet {
uint8_t addr[3];
uint32_t addr_length;
void *buffer;
uint32_t length;
uint8_t chip;
} twi_packet_t;
The parameters of twi_write() are all required to be of type unsigned char.
When compiling, I receive the following error:
expected expression before '{' token
Is there a correct way to do what I'm trying to do here, or is it just not possible?
My take on it, in a compilable sample. This is a compilation stub and will not run correctly, so don't try to run it as-is !
//
// Cobbling up a compilation stub
//
#include <stdint.h>
struct Twi;
typedef struct Twi Twi;
#define MPU_TWI (Twi*)0
typedef struct twi_packet {
uint8_t addr[3];
uint32_t addr_length;
void *buffer;
uint32_t length;
uint8_t chip;
} twi_packet_t;
uint32_t twi_master_write(Twi *p_twi, twi_packet_t *p_packet);
//
// Now for my answer :
//
#define i2c_write(slave_addr, reg_addr, len, data_ptr) \
twi_master_write(MPU_TWI, &(twi_packet_t){ \
.addr = reg_addr, \
.addr_length = 1, \
.buffer = *data_ptr, \
.length = len, \
.chip = slave_addr \
})
main()
{
// Trigger that macro !
i2c_write(0, 0, 0, (void**)0);
}
This instanciates a compound literal and passes its address to the function. The literal's lifetime does not exceed that of the full call expression.
Here's a more readable and correct way to write the macro.
It will work in all cases of if/else clauses and the struct is defined within a scope so it's name is local and doesn't pollute your name space.
#define i2c_write(_slave_addr, _reg_addr, _len, _data_ptr) \
do { \
twi_packet_t temp = { \
.addr = _reg_addr, \
.addr_length = 1, \
.buffer = _data_ptr, \
.length = _len, \
.chip = _slave_addr }; \
\
twi_master_write(MPU_TWI, &temp); \
} while (0)
It would be better if you provide a simple complete set of a code, so that we can execute here and help you. Meanwhile, i dont think you can use the '*' in the macro, since, macro patameters are not typed. What macro does is just a substitution of a symbol.