How to prevent macros from hiding 'const' when casting (C) - c

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)

Related

Why do C macros act as pointers even though I am not passing variables by pointer

I am trying to write a series of C macros to provide some generic data type capability for a struct, or grouping of structs that manages a dynamically allocated array. At this point I have written several structs for each data type and am just starting to write a Macro function that can initialize the struct variables and allocated a user defined amount of memory. The idea is to create one init function that can initialize any type of struct, so as long as it has the write form. For this implementation I first have to instantiate a copy of the struct, which is then passed to the macro. The macro ensures that the variables allocated_length and active_length is of type size_t. Then it determines the type of array by de-referencing it and using thetypeof operator. Finally it allocates memory to ptr and then checks to ensure the allocation was not returned as NULL. However, in this example, I do not pass anything back to the main program, and I am not passing variables as a pointer. Yet, somehow, the struct in the structs in the main program are able to see the modifications I made in the Macro. How is this?
#define init_vector(vec_struct, aloc_length) ({size_t _a = (aloc_length); \
size_t _b = 0; \
typeof(vec_struct.array) ptr = malloc(aloc_length * sizeof(&vec_struct.array)); \
if (ptr == NULL) { \
perror("WARNING: "); \
exit(0); \
} \
vec_struct.allocated_length = _a; \
vec_struct.active_length = _b; \
vec_struct.array = ptr; \
})
typedef struct
{
int *array;
size_t allocated_length;
size_t active_length;
} IntVector;
typedef struct
{
float *array;
size_t allocated_length;
size_t active_length;
} FltVector;
int main() {
IntVector int_vec;
init_vector(int_vec, 30);
printf("%ld\n", int_vec.allocated_length);
FltVector float_vec;
init_vector(float_vec, 20);
printf("%ld\n", float_vec.allocated_length);
return 0;
}
You need to understand that macros are not functions. They simply replace text (or more precise tokens) before the actual C compilation starts.
The compiler will compile this code:
int main() {
IntVector int_vec;
({size_t _a = (30); size_t _b = 0; typeof(int_vec.array) ptr = malloc(30 * sizeof(&int_vec.array)); if (ptr ==
# 32 "/app/example.c" 3 4
((void *)0)
# 32 "/app/example.c"
) { perror("WARNING: "); exit(0); } int_vec.allocated_length = _a; int_vec.active_length = _b; int_vec.array = ptr; });
printf("%ld\n", int_vec.allocated_length);
FltVector float_vec;
({size_t _a = (20); size_t _b = 0; typeof(float_vec.array) ptr = malloc(20 * sizeof(&float_vec.array)); if (ptr ==
# 36 "/app/example.c" 3 4
((void *)0)
# 36 "/app/example.c"
) { perror("WARNING: "); exit(0); } float_vec.allocated_length = _a; float_vec.active_length = _b; float_vec.array = ptr; });
printf("%ld\n", float_vec.allocated_length);
return 0;
}
https://godbolt.org/z/ezvKfdn33
Is it something you have expected?
Macros have to be used with great caution and as little as possible.
From https://en.cppreference.com/w/c/preprocessor/replace:
Function-like macros
#define identifier( parameters ) replacement-list
Function-like macros replace each occurrence of a defined identifier with replacement-list, additionally taking a number of arguments, which then replace corresponding occurrences of any of the parameters in the replacement-list.
The syntax of a function-like macro invocation is similar to the syntax of a function call: each instance of the macro name followed by a ( as the next preprocessing token introduces the sequence of tokens that is replaced by the replacement-list. The sequence is terminated by the matching ) token, skipping intervening matched pairs of left and right parentheses.
...
That means (based on your example) that every occurrence of the identifier init_vector is replaced with the code after the last parentheses of the parameter list.
And each occurrence of the parameters vec_struct, aloc_length will also replaced accordingly.
At the end, it is not about functions and function calls, but replacement.
"The preprocessor supports text macro replacement and function-like text macro replacement."

Is it possible to implement GNU C's typeof(x) with C11's _Generic?

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

Passing a type as a parameter

ETA: This is NOT about malloc(), or memory allocation, it's about passing a type as a parameter, like:
va_arg(l, char);
I'm using malloc() as a simple example.
This might be a stupid question, or perhaps I'm missing something.
Let's imagine I want to write a simple function that allocates some memory, not any particular type of memory but something more flexible.
Like, say I wanted 1,000 chars allocated and returned. So I'd like a function that I can call like this:
ptr = getMem(char, 1000);
Pasing the actual type as a parameter, which could be useful.
Now I know macros like va_arg() can do this:
fprintf(stdout, "%s\n", va_arg(l, char));
So I looked into it a bit, it's all rather vague. I found this:
type va_arg(va_list ap, type)
Parameters
ap − This is the object of type va_list with information about the additional arguments and their retrieval state. This object should be initialized by an initial call to va_start before the first call to va_arg.
type − This is a type name. This type name is used as the type of the expression, this macro expands to.
You can see cleary the type for the first parameter is defined as va_list,
but the second parameter, the one I'm interested in - is simply specified as type.
So it started to bug me, I've been messing around with bum code like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *getMem(type, int size) {
return malloc(sizeof(type) * size);
}
int main(void)
{
void *mem;
mem = getMem(1000, char);
if (mem == NULL) {
perror("malloc()");
exit(EXIT_FAILURE);
}
fprintf(stdout, "Memory allocated successfully!\n");
free(mem);
exit(EXIT_SUCCESS);
}
I've been sniffing around include files trying to figure this out but to no avail, is there a way I can do this?
Sorry if it's a bit vague or nonsensical, but if va_arg() can do it I reckon I should be able to, also.
Much obliged.
Do this with a CPP macro:
#define getMem(type, size) \
malloc(sizeof(type) * size)
However, personally, I prefer this:
#define getMemOf(ptr, size) \
ptr = malloc(sizeof(*ptr) * size)
// invoke with:
getMemOf(ptr, 1000);
_Generic in C99 C11 may offer something close to OP's need.
Example: Code wants to assign the maximum value of a common integer type.
#define integer_max(X) _Generic((X), \
unsigned long long: ULLONG_MAX, \
long long: LLONG_MAX, \
unsigned long: ULONG_MAX, \
long: LONG_MAX, \
unsigned: UINT_MAX, \
int: INT_MAX, \
unsigned short: USHRT_MAX, \
short: SHRT_MAX, \
unsigned char: UCHAR_MAX, \
signed char: SCHAR_MAX, \
char: CHAR_MAX, \
_Bool: 1, \
default: 1/0 \
)
// Here the _type_ of `x` is used by integer_max(), not its value.
some_integer_type x = integer_max(x);
You are going to end up doing this with sizeof anyway. I just checked this in Visual Studio, and Microsoft defines it as (across several defines)
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_arg _crt_va_arg
You can find these in vadefs.h. Long story short, you're not going to get away from using sizeof somewhere, so you should just do it where it is most simple. Personally I think that'd be just passing the size into your getMem function instead of the type will save you way more headache in the long run.
malloc() does not need to know the type to work well, just the size of the type.
Should code want to insure no overflow in the size calculation, a check could be made.
void *getMem(size_t element_count, size_t type_size) {
if (element_count > SIZE_MAX/type_size) return NULL;
return malloc(element_count * size);
}
// usage example
size_t element_count,
void * p = getMem(element_count, sizeof (char));
If one wants zero-ed memory, simple use calloc()
// usage example
size_t element_count,
void * p = calloc(element_count, sizeof (char));
Recommend that code not use void * pointers and expresses a type like char separately. Instead, declare a pointer with a non-void type.
#define ALLOCATE_ASSIGN(addr_ptr, count) (*(addr_ptr)=malloc(sizeof **(addr_ptr) * count))
some_type *mem;
ALLOCATE_ASSIGN(&mem, element_count);

Use of pasting operator `##` with types in C

Is it possible to define a macro for the C preprocessor which takes an array as argument and expands to <type of array elements>_string? For example if x in an array of integers the macro invoked with argument x should expand to int_string.
I tried with
#define TypePaste(array) typeof(array[0])##_string
but it expands to )_string.
Even using multiple levels of indirection for the ## operand the macro doesn't expand correctly.
That's not possible. At the translation phase (the preprocessing phase) where macros are expanded and tokens are concatenated, the compiler (at this point, the preprocessor) does not yet have the notion of a type and thus cannot possibly generate types.
It is not all that clear what problem you are trying to solve, but given your comment:
the macro should expand to the name of an existing function. I'd like to define a function <type>_string for every existing type and then use the macro to select the right function according to the type of the array given.
Then you could use the C11 _Generic keyword:
#include <stdio.h>
void int_string (size_t size, int array[size])
{
printf("I am %s, do stuff here.\n", __func__);
}
void float_string (size_t size, float array[size])
{
printf("I am %s, do stuff here.\n", __func__);
}
#define TypePaste(array) \
_Generic( array, \
int: int_string, \
float: float_string ) \
(sizeof(array)/sizeof(*array), array) // function parameters
int main()
{
int i_arr[5];
float f_arr[3];
TypePaste(i_arr);
TypePaste(f_arr);
}
Output:
I am int_string, do stuff here.
I am float_string, do stuff here.
Note: this assumes that the passed parameter is a local/file scope allocated array. If passing a pointer, there's no type safety and the program will fail.
C11's _Generic type selection is the "proper" way to do what you want. There are other, platform dependent solutions, tough.
If you are using gcc – you don't say so eplicitly, but you use gcc's extension typeof already – you can use gcc's statement expresions and nested functions to create a comparison function for qsort on the spot:
double a[5] = {8.4, 8.1, 9.3, 12.2, 5.2};
qsort(a, 5, sizeof(*a), ({
int cmp(const void *p, const void *q) {
const typeof(a[0]) *pp = p;
const typeof(a[0]) *qq = q;
return (*pp < *qq) ? -1 : (*pp > *qq);
}
cmp;
}));
This creates a function and returns its address. (The last statement of a compound expression is its value. The scope of the local variables is the statement expression, but a nested function is not created on the stack so its safe to return a pointer to that function.)
For primitive types, where you want to sort according to the comparison operators < and >, you can turn that into a macro:
#define COMPARE(ARRAY)({ \
int cmp(const void *p, const void *q) { \
const typeof(ARRAY[0]) *pp = p; \
const typeof(ARRAY[0]) *qq = q; \
return (*pp < *qq) ? -1 : (*pp > *qq); \
} \
cmp; \
})
qsort(a, 5, sizeof(*a), COMPARE(a));
or even:
#define SORT(ARRAY, N) \
qsort(ARRAY, N, sizeof(*ARRAY), COMPARE(ARRAY))
SORT(a, 5);
That's not Standard C, so if you need compatibility between platforms, this is out of the question.

Reference or Ordinary C Type

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.

Resources