Macro assignment to function call - c

Is is possible to define a macro BREF(...):
struct bits
{
int b0:1;
int b1:1;
int b2:1;
int b3:1;
int b4:1;
int b5:1;
int b6:1;
int b7:1;
}
#define BREF(var,bit) ????
#define BAR 4
#define ALIAS BREF(foo,BAR)
unsigned char foo;
such that this statement:
ALIAS = 1;
expands to this:
((struct bits *)&foo)->b4 = 1;
and this:
int k = ALIAS;
to this:
int k = ((struct bits *)&foo)->b4;
So far, this is my implementation of BREF(...):
#define BREF(var,bit) (((struct bits *) &(var))->b##bit)
However, this only works if bit is a literal numeral. I want to be able to pass in a macro variable that expands into a number. How can I make the C preprocessor expand bit before concatenating it to b?

The trick is that the C preprocessor will expand macro arguments only if they are not being used with the stringizing (#) or token-pasting (##) operators. So, to make it work with a macro that expands to a numeric literal, add an extra layer of macros like so:
#define CONCAT(x, y) x ## y
#define BREF(var,bit) (((struct bits *) &(var))-> CONCAT(b, bit))
With this definition, bit is no longer a direct argument of the token-pasting operator, so if it's a macro, it gets expanded before the token-pasting.

You can use an extra step of expansion, like this:
#define BITATTR(num) b##num
#define BREF(var,bit) (((struct bits *) &(var))->BITATTR(bit))

Related

C variable type assert

uint32_t fail_count = 0;
...
if(is_failed)
if(fail_count < UINT32_MAX - 1 )
++fail_count;
It works fine, but this code is fragile. Tomorrow, I may change the type of fail_count from uint32_t to int32_t and I forget to update UINT32_MAX.
Is there any way to assert fail_count is a uint32_t at the function where I have written my ifs?
P.S. 1- I know it is easy in C++ but I'm looking for a C way.
P.S. 2- I prefer to use two asserts than relying on the compiler warnings. Checking the number size via sizeof should work but is there any way to distinguish if type is unsigned?
As of C11, you can use a generic selection macro to produce a result based on the type of an expression. You can use the result in a static assertion:
#define IS_UINT32(N) _Generic((N), \
uint32_t: 1, \
default: 0 \
)
int main(void) {
uint32_t fail_count = 0;
_Static_assert(IS_UINT32(fail_count), "wrong type for fail_count");
}
You could of course use the result in a regular assert(), but _Static_assert will fail at compile time.
A better approach could be dispatching the comparison based on type, again using generic selection:
#include <limits.h>
#include <stdint.h>
#define UNDER_LIMIT(N) ((N) < _Generic((N), \
int32_t: INT32_MAX, \
uint32_t: UINT32_MAX \
) -1)
int main(void) {
int32_t fail_count = 0;
if (UNDER_LIMIT(fail_count)) {
++fail_count;
}
}
As you mentioned GCC, you can use a compiler extension to accomplish this in case you are not using C11:
First write a macro that emulates the C++ is_same. And then call it with the types you want to compare.
A minimal example for your particular case:
#include<assert.h>
#define is_same(a, b) \
static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")
int main()
{
int fail_count = 0;
is_same(fail_count, unsigned int);
}
The compiler asserts:
<source>: In function 'main':
<source>:4:3: error: static assertion failed: "fail_count is not unsigned int"
static_assert(__builtin_types_compatible_p(typeof(a), typeof(b)), #a " is not unsigned int")
^~~~~~~~~~~~~
<source>:9:5: note: in expansion of macro 'is_same'
is_same(fail_count, unsigned int);
^~~~~~~
See Demo
What about a low-tech solution that works even with K&R C and any compiler past and present?
Place the right comment in the right place:
/*
* If this type is changed, don't forget to change the macro in
* if (fail_count < UINT32_MAX - 1) below (or file foobar.c)
*/
uint32_t fail_count = 0;
With a proper encapsulation this should refer to exactly one place in the code.
Don't tell me you increment the fail count in many places. And if you do, what
about a
#define FAIL_COUNT_MAX UINT32_MAX
right next to the declaration? That's more proper and clean code anyway.
No need for all the assertion magic and rocket sciencery :-)

How to determine pointer size preprocessor C

I am working on a software implementation of OpenGL, and OpenGL seems to require that I return 32-bit pointers. To save time, I am putting this into a C equivalent of map with 64-bit systems in order to retrieve 64-bit pointers from 32-bit psuedo-addresses. However, on 32-bit systems, this would cause a hassle, and so I should just use the pointer verbatim.
Here is basically what I want to do in my shared header:
#if <64-bit>
#include <search.h>
extern void * pointerTable;
typedef struct {
int key;
void* value;
} intPtrMap;
inline int compar(const void *l, const void *r) {
const intPtrMap *lm = l;
const intPtrMap *lr = r;
return lm->key - lr->key;
}
inline uint32_t allocate(size) {
void* result = malloc(size);
intPtrMap *a = malloc(sizeof(intStrMap));
a->key = (uint32_t) result;
a->value = result;
tsearch(a, &pointerTable, compar);
return (uint32_t) result;
}
inline int getPtr(ptr) {
intPtrMap *find_a = malloc(sizeof(intPtrMap));
find_a->key = ptr;
void *r = tfind(find_a, &root, compar);
return (*(intPtrMap**)r)->value;
}
#else
inline uint32_t allocate(size) {
return (uint32_t) malloc(size);
}
inline uint32_t getPtr(ptr) {
return (uint32_t) ptr;
}
#endif
Any suggestions on how to do the first if?
How to determine pointer size preprocessor C (?)
To determine pointer size in a portable fashion is tricky.
Various pointers sizes
It is not uncommon to have a pointer to a function wider than a pointer to an object or void*.
Pointers to int char, struct can be of different sizes, although that is rare.
So let us reduce the task to determine void * pointer size.
Pre-processor math
PP math is limited, so code needs to be careful. Let us stay with integer math.
(u)intptr_t
The optional types (u)intptr_t, which are very commonly available, are useful here. They allow conversion of a void * to an integer and then to an equivalent void*.
Although the integer type size may differ from the pointer type, that, I assert is rare and detectable with _Static_assert from C11.
Following will handle many C11 platforms. Useful ideas toward a general solution.
#include <stdint.h>
// C11
_Static_assert(sizeof (void*) == sizeof (uintptr_t),
"TBD code needed to determine pointer size");
// C99 or later
#if UINTPTR_MAX == 0xFFFF
#define PTR16
#elif UINTPTR_MAX == 0xFFFFFFFF
#define PTR32
#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu
#define PTR64
#else
#error TBD pointer size
#endif
[Edit 2021]
With Is there any way to compute the width of an integer type at compile-time?, code could use, at compile time, the below to find the width of uintptr_t.
/* Number of bits in inttype_MAX, or in any (1<<k)-1 where 0 <= k < 2040 */
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
#define UINTPTR_MAX_BITWIDTH IMAX_BITS(UINTPTR_MAX)
Using other questions on StackOverflow and also a solution from somebody on Discord, I have cobbled together this solution:
#if _WIN32 || _WIN64
#if _WIN64
#define PTR64
#else
#define PTR32
#endif
#elif __GNUC__
#if __x86_64__ || __ppc64__
#define PTR64
#else
#define PTR32
#endif
#elif UINTPTR_MAX > UINT_MAX
#define PTR64
#else
#define PTR32
#endif
This should be able to reliably determine 64-bit or 32-bit pointer usage in preprocessor.

Using macro within another macro declaration

Let's start with the code and the error.
#define BitMap_getMask(range) (((~(unsigned int)0>>(31-range.b+range.a))<<range.a))
#define BitMap_get(x, range) (x & BitMap_getMask(range))
#define awesome (range){4,6}
...................
printf("%08x\n", BitMap_get(0xEEEEEEEE, awesome));
Now the error from the compiler. Line 29, the line with the printf.
error: macro "BitMap_getMask" passed 2 arguments, but takes just 1
error: 'BitMap_getMask' undeclared (first use in this function)
I'm working on a small library which will help me with bitwise operations. When trying to use a macro within another macro I am getting this error.
When range is expanded to {4,6} and passed to BitMap_getMask, what you're getting is BitMap_getMask({4,6}) which is 2 arguments, whereas BitMap_getMask expects 1 argument.
Furthermore, the pre-processor only does text replacement for these macros. It is unaware of type. It will replace every instance of text "range" with text "{4,6}" so you don't have a type (struct range) or instance of a type, that you can use, just some text, so "range.a" and "range.b" are also not going work; they would result something like "{4,6}.a" and "{4,6}.b"
Not valid C.
C99 supports inline functions, and there is almost no excuse for using pre-processor macros in C these days. They are trouble (one good use of course is include guards). Inline functions are in the domain of the compiler and properly type-checked.
struct awesome
{
unsigned int a;
unsigned int b;
};
...
static inline unsigned int BitMap_get(unsigned int x, awesome range)
{
return (x & BitMap_getMask(range));
}
static inline unsigned int BitMap_getMask(awesome range)
{
return (((~(unsigned int)0>>(31-range.b+range.a))<<range.a));
}
...
awesome range =
{
.a = 4,
.b = 6,
};
unsigned int x = 0xEEEEEEEE;
unsigned int bm = BitMap_get(x, awesome);
...
This might be what you need
#define BitMap_getMask(range) \
(((~(unsigned int) 0 >> (31 - (range).max + (range).min)) << (range).min))
#define BitMap_get(x, range) \
((x) & BitMap_getMask(range))
#define awesome \
((struct {int min; int max;}){4, 6})
the error was due to the expansion of {4, 6}.

Is there a way to make an enum unsigned in the C90 standard? (MISRA-C 2004 compliant)

I'm trying to find a way to make an enum "unsigned".
enum{
x1 = 0,
x2,
x3
};
uint8_t = x2; /* <--- PC-LINT MISRA-C 2004 will complain about mixing signed and unsigned here */
Of course, I can add a typecast to get rid of the error, that is time consuming and error prone.
uint8_t = (uint8_t)x2; /* This works, but is a lot of extra work over the course of 1000s of lines of code*/
So, is there a way to make a specific enum unsigned that MISRA-C 2004 will like?
There is no standard C way to control the type chosen for an enum. You can do it in implementation specific ways sometimes, like by adding a value to the enumeration that forces the type to be unsigned:
enum {
x1,
x2,
x3,
giant_one_for_forcing_unsigned = 0x80000000;
};
But that's not even standard C, either (since the value provided won't fit in an int). Unfortunately, you're pretty much out of luck. Here's the relevant bit from the standard:
6.7.2.2 Enumeration specifiers, paragraph 4
Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration. The enumerated type is incomplete until immediately after the } that terminates the list of enumerator declarations, and complete thereafter.
You might be better off using #define rather than enum to make your constants:
#define x1 0U
#define x2 1U
#define x3 2U
uint8_t x = x2;
There are several concerns here, where there is a slight potential for conversion bugs, which MISRA is trying to make you avoid:
Enum constants, that is x1 etc in your example, are guaranteed to be of type int (1). But enum variables and the variable type enum is not guaranteed to be of the same type (2), if you are unlucky it is defined to be a small integer type and thereby subject to the integer promotion rules.
MISRA bans implicit conversions for large integer types to smaller ones, mainly to dodge unintentional truncation of values, but also to dodge various implicit promotion rules.
Your specific MISRA-compliance error actually comes from the latter concern above, violation of rule 10.3 (3).
You can either solve this by adding an explicit cast to the "underlying type" (intended type), in this case a cast to uint8_t. Or you can solve it by never using enums at all, replace them with #defines. That might sound very radical, but keep in mind that C has no type safety whatsoever, so there is no apparent benefit of using enums apart from perhaps readability.
It is somewhat common to replace enums in this manner:
#define FALSE 0
#define TRUE 1
typedef uint8_t BOOL;
(Though the purpose in this example is mainly to make the BOOL type portable, with a guarantee to be 8 bits and never 16 bits, as might happen in case it was an enum.)
References:
(1) C11 6.2.7.7/2:
"The expression that defines the value of an enumeration constant
shall be an integer constant expression that has a value representable
as an int."
(2) C11 6.2.7.7/4:
"Each enumerated type shall be compatible with char, a signed integer
type, or an unsigned integer type. The choice of type is
implementation-defined, but shall be capable of representing the
values of all the members of the enumeration."
(3) MISRA-c:2004 rule 10.3:
"The value of a complex expression of integer type may only be cast to
a type that is narrower and of the same signedness as the underlying
type of the expression."
Not only is there not a way in C90 to specify that an enum take on an unsigned type, but in C90:
An identifier declared as an enumeration constant has type int
This also applies to C99 (6.4.4.3). If you want an unsigned type, you're looking at a language extension.
The enumeration type may be something other than int, but the constants themselves must have int type.
You can force it to be unsigned by including a value large enough that it cannot fit in an int (per specification). This is pretty simple for types >= sizeof int, but unsigned char/short is more complicated and requires compiler specific packing. Of course implementations could technically still represent UINT_MAX as an unsigned long long... not that I've ever seen though.
#include <stdio.h> //only included for printf example
#include <limits.h>
#include <stdint.h>
/** set up some helper macros **/
#ifdef _MSC_VER
#define PACK( ... ) __pragma( pack(push, 1) ) __VA_ARGS__ __pragma( pack(pop) )
#else /* for gcc, clang, icc and others */
#define PACK( ... ) __VA_ARGS__ __attribute__((__packed__))
#endif
#define _PASTE(x,y) x ## y
#define PASTE(x,y) _PASTE(x,y)
/* __LINE__ added for semi-unique names */
#define U_ENUM(n, ... ) \
enum n { __VA_ARGS__ , PASTE( U_DUMMY , __LINE__ ) = UINT_MAX }
#define UL_ENUM(n, ... ) \
enum n { __VA_ARGS__ , PASTE( UL_DUMMY , __LINE__ ) = ULONG_MAX }
#define SZ_ENUM(n, ... ) /* useful for array indices */ \
enum n { __VA_ARGS__ , PASTE( SZ_DUMMY , __LINE__ ) = SIZE_MAX }
#define ULL_ENUM(n, ... ) \
enum n { __VA_ARGS__ , PASTE( ULL_DUMMY , __LINE__ ) = ULLONG_MAX }
#define UC_ENUM(n,...) \
PACK(enum n { __VA_ARGS__ , PASTE( UC_DUMMY , __LINE__ ) = UCHAR_MAX })
#define US_ENUM(n,...) \
PACK(enum n { __VA_ARGS__ , PASTE( US_DUMMY , __LINE__ ) = USHRT_MAX })
Here is a check to see that it works as expected:
typedef UC_ENUM(,a) A_t;
typedef US_ENUM(,b) B_t;
typedef U_ENUM(,c) C_t;
typedef UL_ENUM(,d) D_t;
typedef ULL_ENUM(,e) E_t;
typedef SZ_ENUM(,e) F_t;
int main(void) {
printf("UC %d,\nUS %d,\nU %d,\nUL %d,\nULL %d,\nSZ %d,\n",sizeof(A_t),
sizeof(B_t),sizeof(C_t),sizeof(D_t),sizeof(E_t),sizeof(F_t));
return 0;
}
To be more like a standard enum statement this is slightly different than the simpler version I use, which takes an additional named parameter for the last enum instead of the __LINE__ hack (this is also useful for functions that return -1 on error, because it will cast to U*_MAX)
Here is how that version looks:
#define U_ENUM( n, err, ...) enum n { __VA_ARGS__ , err = UINT_MAX }
#define UL_ENUM(n, err, ...) enum n { __VA_ARGS__ , err = ULONG_MAX }
#define ULL_ENUM(n,err, ...) enum n { __VA_ARGS__ , err = ULLONG_MAX}
#define SZ_ENUM(n, err, ...) enum n { __VA_ARGS__ , err = SIZE_MAX }
#define UC_ENUM(n, err, ...) PACK(enum n { __VA_ARGS__ , err = UCHAR_MAX })
#define US_ENUM(n, err, ...) PACK(enum n { __VA_ARGS__ , err = USHRT_MAX })
Apart from packing enums in char or short for compactness, size_t enums are the most interesting, because they can be used as array indices without an extra MOV instruction.
typedef SZ_ENUM(message_t,MSG_LAST,MSG_HELLO,MSG_GOODBYE,MSG_BAD) message_t;
static const char *messages[]={"hello","goodbye","bad message"};
void printmsg(message_t msg){
if (msg > MSG_BAD) msg = MSG_BAD;
(void) puts(messages[msg]);
}
Note if you use C++11 vs C, you can enum Foo : char { A, B, C}; or enum class Bar : size_t { X, Y, Z};
In addtion to #Carl's answer, to get some of the benefits of an enum declaration and result in some unsigned type, code could use the below.
// Form values 0, 5, 6
enum {
x1,
x2 = 5,
x3
};
// Form values 0u, 5u, 6u
#define ux1 (1u * x1)
#define ux2 (1u * x2)
#define ux3 (1u * x3)
This may not help with enumerations constants outside the int range.
Of course code could do the conversion instead as OP knows.
// uint8_t = x2;
uint8_t = x2 * 1u;

The ## operator in C

What does ## do in C?
Example:
typedef struct
{
unsigned int bit0:1;
unsigned int bit1:1;
unsigned int bit2:1;
unsigned int bit3:1;
unsigned int bit4:1;
unsigned int bit5:1;
unsigned int bit6:1;
unsigned int bit7:1;
} _io_reg;
#define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bit##bt
(I know what it all does besides the ## part.)
It is string concatenation, as part of the preprocessor macro.
(In this context, "string" refers to a preprocessor token of course, or a "string of source code", and not a C-string.)
It's called the pasting operator; it concatenates the text in bt with the text bit. So for example, if your macro invocation was
REGISTER_BIT(x, 4)
It would expand to
((volatile _io_reg*)&x)->bit4
Without it, you couldn't put a macro argument directly beside text in the macro body, because then the text would touch the argument name and become part of the same token, and it'd become a different name.
The operator ## concatenates two arguments leaving no blank spaces between them:
#define glue(a,b) a ## b
glue(c,out) << "test";
That is the token pasting operator.
That's part of the macro definition.
It allows you to concatenate strings inside the macro.
In your case, you can use bt from 7 to 0 like this:
REGISTER_BIT(myreg, 0)
and it will be expanded as:
((volatile _io_reg*)&myreg)->bit0
Without this, you'd have to define the bit part of the macro as one of the macro's arguments:
#define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bt
where the usage would be:
REGISTER_BIT(myreg, bit0)
which is more cumbersome.
This also allows you to build new names.
Assume you have these macros:
#define AAA_POS 1
#define AAA_MASK (1 << AAA_POS)
#define BBB_POS 2
#define BBB_MASK (1 << BBB_POS)
and you want a macro that extracts AAA from a bit vector. You can write it like this:
#define EXTRACT(bv, field) ((bv & field##_MASK) >> field##_POS)
and then you use it like this:
EXTRACT(my_bitvector, AAA)
It's not a C construct, it's a preprocessor feature. In this case it's meant to evaluate the bt variable and concatenate it with the bit prefix. Without the hashes you would have bitbt there, which obviously would not work.
Here's an example from ffmpeg, a macro that registers both audio and video filters:
#define REGISTER_FILTER(X, x, y) \
{ \
extern AVFilter ff_##y##_##x; \
if (CONFIG_##X##_FILTER) \
avfilter_register(&ff_##y##_##x); \
}
and usage can be:
REGISTER_FILTER(AECHO,aecho,af);
REGISTER_FILTER(VFLIP,vflip,vf);

Resources