I was browsing the linux kernel and there is something I don't fully understand. So while browsing container_of.h we find the following definition:
#define container_of(ptr, type, member) ({ \
void *__mptr = (void *)(ptr); \
static_assert(__same_type(*(ptr), ((type *)0)->member) || \
__same_type(*(ptr), void), \
"pointer type mismatch in container_of()"); \
((type *)(__mptr - offsetof(type, member))); })
I know exactly what the macro is doing because I used intrusive linked lists before, but normally the definition I use is a one liner something like:
#define container_of(__ptr__, __type__, __member__) ((__type__*)(__ptr__ - offsetof(__type__, __member__)))
What is escaping from my understanding is the semantic meaning of that multi line assignment, on a normal basis what you would do is something like
type* name = container_of(ptr, type, member) which would expand to
type* identifier = ({
void *__mptr = (void *)(ptr);
static_assert(__same_type(*(ptr), ((type *)0)->member) ||
__same_type(*(ptr), void),
"pointer type mismatch in container_of()");
((type *)(__mptr - offsetof(type, member))); })
As a POC I wrote something easier
#define POC(__x__) ({assert(__x__ == __x__); 2;})
int __x__ = POC(0);
printf("__x__: {%d}", __x__);
// 2 gets printed
Could someone please explain to me how this is able to compile and the semantic meaning of several statements for this just one and only assignment (I mean can I always assume the last value is the one used for the assignment or something like that)?
My understanding of brackets on C is that we can embed them to create new scopes wherever we want successfully emulating variable shadowing if we want so:
int main () {
int x = 0;
printf("x: {%d}", x); // Prints 0
{
int x = 1;
printf("x: {%d}", x); // Prints 1
}
}
But I never seen the above usage of a new scope for embedding context to the assignment
For whoever answers, thanks.
Related
To make some code compile in C and C++ I use this in a few places:
#ifdef __cplusplus
#define typeof(x) decltype(x) // works ok in most cases, except C++ reference types
#endif
char* a = (typeof(a)) malloc(4);
In C, this compiles to char* a = (char *) malloc(4) where the cast is totally unecessary, but in C++ void * is not implicitly promoted to char * and an error is issued if a cast is not present.
This is just as well when I can compile with -std=gnu11 on GCC or Clang, but what when I want to make my code compile as ISO C11? I thought I could use C11's _Generic to implement typeof(x) to cast some types:
#define gettype(x) _Generic((x), \
short: (short ), \
char: (char ), \
char*: (char *), \
default: (void *) )
int main (void) {
short a = (gettype(a)) 1;
return a;
}
But no matter what type defined in gettype(x) is given in a's declaration,
typeof.h: In function ‘main’:
typeof.h:2:24: error: expected expression before ‘,’ token
short: (short ), \
^
typeof.h:8:13: note: in expansion of macro ‘gettype’
char a = (gettype(a)) 1;
^~~~~~~
typeof.h:8:25: error: expected ‘,’ or ‘;’ before numeric constant
char a = (gettype(a)) 1;
gcc -E says that line expands just fine:
short a = (_Generic((a), short: (short ), char: (char ), char*: (char *), default: (void *) )) 1; ^
Is there some syntax I am missing, or is it simply not possible in C to generate cast code using _Generic?
The problem is that you can't have a partial expression inside the generic selection. A possible work-around could be to put a full expression inside it:
#define cast(from, to) _Generic((from), \
short: (short) (to), \
char: (char) (to), \
char*: (char*) (to), \
default: (void*) (to))
int main (void) {
short a = cast(a, 1);
return 0;
}
No, it's not possible. (Now watch someone prove me wrong!)
In a _Generic expression, each generic-association is either
type-name : assignment-expression
or
default : assignment-expression
It can't be a type name or something that expands to a type name. In particular, though a _Generic expression is resolved at compile time, it is not a macro. The final result is always an expression.
And I don't believe there's any other way to do what you want in standard C.
I just figured out..if Visual C++, in C, not C++, if you have two unrelated non-void pointer result types in a ternary expression, the type of the ternary expression is the first.
This can be useful.
So, in a corner I am painted into where I have a bunch of C code, I need to cast a void* to the type of something else, within a macro, that should not double evaluate...
typedef struct DesiredType { ... } DesiredType;
typedef struct ArbitraryType { ... } ArbitraryType;
ArbitraryType/*void*/* function_to_void_double_eval (void* a)
{
...
}
#if defined(_MSC_VER) && !defined(__cplusplus)
#define MACRO(x) (0 ? (DesiredType*)0 : function_to_avoid_double_eval(x))
#else // assume gcc
use typeof and temporaries in a macro
#endif
I have a macro which takes 2 args, one value is modified and to get an offset I have to cast.
#define MY_MACRO(dst, src) \
do_something((char *)dst + offset, (char * )src + offset)
In the example above, dst will be modified, however if the value is const, the cast to (char *) will hide this.
However, I don't want this macro to silently hide const members.
static void my_function(const float *a, const float *b)
{
MY_MACRO(a, b); /* <-- this should warn because 'a' is const */
}
I was wondering if there is a good way to ensure a variables cast within a macro is not hiding const.
Moved example solution into own answer - https://stackoverflow.com/a/25072965/432509
What's the one thing you can't do with const types? Assign to them. Therefore, how to get the compiler's attention that we shouldn't be using const pointers in this position? Try to assign through them!
Add an extra line to the definition:
#define MY_MACRO(dst, src) \
((void)(0 ? ((void)(*(dst) = *(dst)), *(src) = *(src)) : 0), \
do_something((char *)dst + offset, (char * )src + offset))
Because of the 0 ? ..., the inserted line will never actually do anything (and with the void casts it shouldn't trigger warnings either), but it's a C-level expression and that means the compiler must check it before optimization begins; the fact it never runs, has no effects, and will be removed before code generation doesn't mean it's allowed to skip the type check. Only pointers to non-const will pass.
The value being assigned is sourced from the same pointer so that it will work with any type; since the line never runs, we won't have any multiple-evaluation problems from the multiple appearances of the name. Using ?: instead of if means we can put this in a comma expression in case do_something needs to return a value.
Pointer Assignment (simple)
You can ensure a pointer variable isn't const by assigning to a dummy void pointer.
/* reusable macro to ensure a var's not const */
#define CHECK_TYPE_NONCONST(var) do { \
void *not_const = (0 ? (dst) : NULL); \
(void)not_const; \
} while(0)
#define MY_MACRO(dst, src) do { \
CHECK_TYPE_NONCONST(dst); \
do_something((char *)dst + offset, (char * )src + offset); \
} while(0)
This works with gcc, warning: initialization discards 'const' qualifier from pointer target type,
The 0 ? (dst) means we don't instantiate dst as result of the typecheck (in case its a function call or contains an increment or assignment).
Pointer Assignment (using typeof)
Its possible that dst is a function call, in that case the compiler may not optimize it out, so we can use the typeof extension (if its available).
/* reusable macro to ensure a var's not const */
#define CHECK_TYPE_NONCONST(var) do { \
void *non_const = ((typeof(var))0); \
(void)non_const; \
} while(0)
#define MY_MACRO(dst, src) do { \
CHECK_TYPE_NONCONST(dst); \
do_something((char *)dst + offset, (char * )src + offset); \
} while(0)
C11 _Generic
If C11 is supported and the input type(s) are known, you can ensure a const isn't assigned in a cast.
By omitting the const struct SomeStruct case.
#define MY_MACRO(dst, src) do { \
(void)_Generic(dst, struct SomeStruct *: 0); \
do_something((char *)dst + offset, (char * )src + offset); \
} while(0)
This has the outcome of of having typed augments to the macro (which might be useful too, depending on the case)
Here's a challenge question. I would like to create a mask bitmap for an unknown variable type that might be an array. For instance,
char ch;
int i;
int i_arr[2];
printf("The ordinary type for ch is %lu bytes.\n", sizeof(ORDINARY_TYPE(ch)));
printf("The ordinary type for i is %lu bytes.\n", sizeof(ORDINARY_TYPE(i)));
printf("The ordinary type for i_arr is %lu bytes.\n", sizeof(ORDINARY_TYPE(i_arr)));
The output should be:
The ordinary type for ch is 1 bytes.
The ordinary type for i is 4 bytes.
The ordinary type for i_arr is 4 bytes.
Sounds impossible? It's not. To give you a jump start I will provide my "solution" - be warned that it is very GCC specific although I wonder if the builtins could be rewritten to be more compiler agnostic.
#define IS_PTR(X) \
__builtin_choose_expr( \
__builtin_types_compatible_p(typeof(X), char*), \
1, \
__builtin_choose_expr( \
__builtin_types_compatible_p(typeof(X), int8_t*), \
1, \
__builtin_choose_expr( \
__builtin_types_compatible_p(typeof(X), uint8_t*), \
1, \
(((uintptr_t)((1 ? (X) : (uintmax_t)0)+1) - \
(uintptr_t)(1 ? (X) : (uintmax_t)0)) != 1)? 1 : 0 \
)))
#define ORDINARY_TYPE(X) \
typeof(* __builtin_choose_expr( \
__builtin_types_compatible_p( \
typeof(*(IS_PTR(X)? (X) : (&(X)))), void), \
((X)), \
(&(X)) \
))
Here I have taken advantage of the result from IS_PTR(X)? (X) : (&(X)) returning void * if X is a pointer. However, as a result, the GCC compiler gives the following warnings (depending on the type of X):
warning: pointer/integer type mismatch in conditional expression [enabled by default]
warning: pointer type mismatch in conditional expression [enabled by default]
Can anyone do this without getting these warnings and make it 'friendlier'?
Use
I am working on a general GPIO configuration library (lol). I think that I have something fairly solid but obviously it will need more rigorous testing for other processors. One of the 'golden nuggets' is configuring a GPIO pins' properties,
CPU_GPIO_CONFIG_PROP(gpio, pupd, 2); // Pull up/down, Open Drain, or none
CPU_GPIO_CONFIG_PROP(gpio, af, 4); // Alternative Functions
Where CPU_GPIO_CONFIG_PROP is defined like so,
extern struct cpu_gpio;
#define CPU_GPIO_CONFIG_PROP(_gpio, _prop, _size) ({ \
struct cpu_gpio *bus = (_gpio)->bus_addr; \
ORDINARY_TYPE( ((struct cpu_gpio *) 0)->_prop) prop_type; \
const size_t prop_size = sizeof(prop_type); \
const unsigned short pin = ((_size)*(_gpio)->pin) % (8*prop_size); \
const typeof(prop_type) mask = ~(~((typeof(prop_type)) 0x0) << _size); \
typeof(prop_type) *p = ((typeof(prop_type) *) &bus->_prop \
+ ((_size)*((_gpio)->pin)/(8*prop_size))); \
*p = (*p & ~(mask << pin)) | (((typeof(prop_type)) gpio->_prop) << pin); \
})
PHEW! Okay, someone is going to once again ask "Why?" (#nneonneo)... The simple answer ('cause this is getting too long) is that each GPIO property is generally 8*_size < sizeof(int) (32 bit ARM processor). Here _size is the number of bits that the property takes to describe it. However, it is possible for a property to exceed this requirement and therefore take 8*_size > sizeof(int). In this case, the property takes up int[n] space in memory and will require some additional math to figure out (as I have already done above). In my example, af takes 4 bits to describe (5 possible alternative functions to select from). For 16 pins this becomes 4*16 > 32 and therefore takes int[2] to describe. The beauty and simplicity of this is that I only need the one macro to set all of the GPIO properties!
BTW, feel free to reuse if you feel it worthy. Just remember to give me a little shout out!
Couple of notes
This does not work for void*, intXX_t ** (or any pointer referencing more than one pointer and therefore &(int[n]) even though (void *)ARR == (void *)&ARR).
__builtin_types_compatible_p(typeof(char), int8_t, ...) evaluates to false.
(uintptr_t)((X)+1) - (uintptr_t)(X) != 1 is a test for pointer math.
I have tried to work with the container_of macro in linux kernel.
what I get by google is as follow
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) \
({ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define CONT(prt, type, mem) container_of((prt), type, mem)
struct test {
int a;
};
struct m {
int b;
struct test t;
int c;
};
int main(int argc, char *argv[])
{
/* existing structure */
struct m *ma;
ma = malloc(sizeof(struct m));
ma->t.a = 5;
ma->b = 3;
/* pointer to existing entry */
struct test *te = &ma->t;
struct m *m = CONT(te, struct m, t);
printf("m->b = %d\n", m->b);
return EXIT_SUCCESS;
}
o/p
m->b = 3
but I am having the doubt in the assignment of *m .I have tried following
#include <stdio.h>
int main()
{
int x = (int k = 9;k-2;);
printf("x= %d k = %d",x,k);
}
o/p
one.c:5: error: expected ‘)’ before ‘k’
one.c:5: error: expected expression before ‘;’ token
one.c:6: error: ‘k’ undeclared (first use in this function)
one.c:6: error: (Each undeclared identifier is reported only once
one.c:6: error: for each function it appears in.)
If this assignment is wrong here then how it is working in container of macro.what is the difference in above two.(I know one is macro and other is normal declaration but after macro expansion both will look same)
Note:Excuse me as this may be a simple but I am not able to figure it out.
kinldy give some solution to my dobut.
This is using special gcc features, namely block expressions ({ }). These allow to to have a object definition inside an expression. The last statement in this construct determines the value of the block expression.
So you missed the additional { } inside the expression for your test case.
Also:
there is no assignment in that macro, but only initialization of the local variable
the typeof operator in there also is a gcc extension
I am adding my answer to this question because I got some point .It may help other.
#include <stdio.h>
int main()
{
int x = ({int k = 9;k-2;});
printf("x = %d",x);
}
o/p
x = 7
As Jens said above its all true I have missed the { } but addition to that ,I am printing the value of k which is not correct as all the value created with in the ({ }) are temporary and will delete as soon as the value of expression is evaluated.
http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs
This question already has answers here:
Implementing a generical 'map' function over arrays in C
(3 answers)
Closed 10 years ago.
how can i define a general map operation on an array in C?
ideally I want something like python's map(function,array) ~~ but as a macro. I believe this would be something like C++'s std::transform, but would be in C, and not use iterators..
(this would be unary operation)
I was thinking something like:
template <class T*, class U*,size_t N>
T* map(T (*func)(U), U* arr,size_t N)
{
T* tmp = (T*)malloc(sizeof(T) * N);
size_t i;
for(i=0;i<N;i++)
{
*(tmp+i) = *func(*(arr+i));
}
}
... but of course templates are in C++..
so how can I 1) do the latter and 2) if you could, could you fix the above code snippet.
Thanks
For a template like this, there is a fairly straightforward translation to macros; the major syntactic wrinkle is that you can't return the result array, the variable to write it to has to be another parameter.
#define map(func_, input_, output_, type_, n_) do { \
output_ = xmalloc(sizeof(type_) * (n_)); \
size_t i_; \
for (i_ = 0; i_ < (n_); i_++) \
output_[i_] = func_(input_[i_]); \
} while (0)
This is not as type-unsafe as it looks, provided you pay attention to your compiler warnings. However, it is not particularly safe if any of the actual arguments to a use of this macro isn't a simple identifier. Most importantly, catastrophic things will happen if any of the actual arguments has side effects.
This can be cured, as can the inability to return the result array, but only if you're willing to use GNU extensions...
#define gnumap(func_, input_, type_, n_) ({ \
__typeof(func_) func__ = (func_); \
__typeof(input_) input__ = (input_), \
output__ = xmalloc(sizeof(type_) * n__); \
__typeof(n_) n__ = (n_), \
i__; \
for (i__ = 0; i__ < n__; i__++) \
output__[i__] = func__(input__[i__]); \
/* return */ output__; \
})
Would I do either of these in real life? Probably not, but sometimes it really is the least bad available option. Think of it as one step shy of rewriting that critical inner loop in assembly language.
(xmalloc, in case you're unfamiliar with it, is the conventional name for a user-written wrapper around malloc that either succeeds or crashes the entire program. I use it here to dodge the question of how to cope with malloc failing.)
So, you could write a function that takes a function pointer and a void * (or char *) to the data, and a data-size.
I certainly wouldn't use only macros to do this, but you may have a macro that doe something like:
#define MAP(func, type, arr, size) map(func, sizeof(type), arr, size)
and map is the function I describe above.