#define an object with no value - c

I am now read some c code. And is not very clear about the "#define someting" expression.
For example, I saw this code:
typedef enum cairo_path_op {
CAIRO_PATH_OP_MOVE_TO = 0,
CAIRO_PATH_OP_LINE_TO = 1,
CAIRO_PATH_OP_CURVE_TO = 2,
CAIRO_PATH_OP_CLOSE_PATH = 3
} __attribute__ ((packed)) cairo_path_op_t; /* Don't want 32 bits if we can avoid it. */
#ifndef __GNUC__
#define __attribute__(x)
#endif
I take attention to the "__attribute__(x)". since in other header file , the "__attribute__(x)" is defined with no value, but how it take effect in the enum "cairo_path_op" define?

This is for portability reasons.
__attribute__() is a GCC extension for modifying various properties and behavior of functions, variables, types, etc.
If a non-GCC-compatible compiler tries to compile code that uses this extension, it won't able to do so and will throw a syntax error.
In order to avoid this, the author of the code makes the preprocessor replace this keyword with nothing if __GNUC__ is not defined (i. e. if the compiler is not a GCC-compatible one), so that the code builds on a bigger variety of platforms.

Related

Is it possible to write a _Static_assert in GCC/GNU C that would verify the layout of bit fields in memory at compile time?

Suppose that I have the following definitions:
#include <stdbool.h>
#include <stdint.h>
#define ASSERT(cond) _Static_assert(cond, #cond)
typedef union {
struct {
bool bit0:1;
bool bit1:1;
bool bit2:1;
bool bit3:1;
bool bit4:1;
bool bit5:1;
bool bit6:1;
bool bit7:1;
};
uint8_t bits;
} byte;
ASSERT(sizeof(byte) == sizeof(uint8_t));
Is it possible to write a code, such as
#include <assert.h>
// ...
assert(((byte) { .bit0 = 1 }).bits == 0b00000001);
assert(((byte) { .bit1 = 1 }).bits == 0b00000010);
assert(((byte) { .bit2 = 1 }).bits == 0b00000100);
assert(((byte) { .bit3 = 1 }).bits == 0b00001000);
assert(((byte) { .bit4 = 1 }).bits == 0b00010000);
assert(((byte) { .bit5 = 1 }).bits == 0b00100000);
assert(((byte) { .bit6 = 1 }).bits == 0b01000000);
assert(((byte) { .bit7 = 1 }).bits == 0b10000000);
// ...
that would cause a compile-time failure if the above conditions weren't satisfied?
(When I try to place the conditions in the ASSERT macro, the compiler complains that expression in static assertion is not constant, which of course makes perfect sense)
The solution is allowed to use the GNU extensions to the C language.
I don't think you can.
_Static_assert is required to verify that the argument expression satisfies standard C's requirements for an integer constant expression.
There are ways, which on gcc can sometimes turn a boolean expression that doesn't satisfy those requirements but are compile-time-known to the optimizer into a compile-time error or warning.
E.g., :
#include <assert.h>
#if __GNUC__ && !__clang__
#define $SassertIfUCan0(X) \
(__extension__({ /*ellicit a -Wvla-larger-than */ \
(!__builtin_constant_p(X)) ? 0 : \
({ char volatile $SassertIfUCan0_[ (!__builtin_constant_p(X)||(X)) ? 1:-1]; \
$SassertIfUCan0_[0]=0,0;}); \
__auto_type $SassertIfUCan0 = X; \
assert($SassertIfUCan0); \
0; \
}))
#endif
int main(int C, char **V)
{
int x = 0; $SassertIfUCan0(x);
//these also ellicit compile-time errrors:
/*$SassertIfUCan0(C-C);*/
/*$SassertIfUCan0(C*0);*/
}
can turn the nullness of the compile-time known variable x, which isn't technically an integer constant, into a compile/time warning/error
("-Wvla-larger-than").
Unfortunately, the macro doesn't work with every expression and that includes your bitfield-based example.
(I wish compilers had a mechanism for failing compilation if an expression happens to be compile-time known and false.)
So AFAIK, the closest thing you can do is compile-time detect platforms whose ABI is known to guarantee your required bitfield layout:
#if __linux__ && __x86_64__
#elif 0//...
//...
#else
#error "bitfields not known to be little-endian"
#endif
I think, this is an X-Y problem: You are asking about checking the layout of bitfields when you really want to write code that is portable across different implementations of bitfields. So:
If you don't try to communicate your bitfield to another machine, or store it in a file where a different machine may read it, just forget about the implementation detail of how the bits are ordered. Just access them via the bitfield names, and be done with it.
If you need to communicate the structures containing these bitfields, declare a uint8_t and the appropriate set of bit flag constants (#define BIT7 (1u << 7), etc.). Bytes never change value when they are transferred from one machine to another, so myFlags & BIT7 is guaranteed to yield the same result everywhere.
Note that it is important to either use a single byte to store the flags, or handle the problem of endianess explicitly.
On GNU Linux, you might find <features.h> and /usr/x86_64-linux-gnu/include/linux/byteorder/big_endian.h
The solution is allowed to use the GNU extensions to the C language.
With most recent GCC compilers, you could provide your own GCC plugin defining your __your_builtin_endian__ compiler builtin. Notice that some GCC compilers are built without plugin support (e.g. RedHat did that). Check by running gcc -v alone.
Once your plugin defines __your_builtin_endian__, you could use that in static_assert. Or have your plugin define and implement some #pragma MYPLUGIN check endian which would make a compile-time error in some cases.
Do budget a few weeks of fulltime work for such a plugin. It is GCC version specific (not always the same C++ code for a GCC 9 and GCC 10 plugin).
Consider also using autoconf (at least if you do not need any cross-compilation).
Not strickly within the limits of the question, but may provide for more portable solution.
The static assertion has limits to the expressions, and it will NOT be able to evaluate expression from a union.
As an alternative, and assuming the code will be built by a makefile (or equivalent), consider adding a a step to the build to force the condition
static.verify: static_check.c
cc -o static_check static_check.c
./static_check
touch $#
# Make the static.verify dependency for building objects/executable.
a.o: static.verify
Basically, making it a requirement to run the small program 'static_check.c'. The program can produce any required error message. Should exit with non-zero return status to indicate an error.

static assert for C90 on gcc

static_assert() is a pretty great capability available since C11.
For pre-C11 compilers though, this capability must be emulated.
It's not too hard, there are many examples available over Internet.
For example :
#define STATIC_ASSERT(CONDITION, MSG) \
typedef char static_assert_##MSG[(CONDITION)?1:-1]
This makes it possible to transfer an error message in the condition, which is handy to explain what's going wrong if it ever gets triggered.
However, this MSG is a lot different from the one in C11's static_assert() :
It must be a single word
It must use only identifier characters
It cannot be a string with double quotes
This is so different from C11's static_assert() that it seems impossible to create a macro which would switch transparently between the C11 and the C90 version depending on the compiler.
In an effort to accept an error message which "looks like C11", aka a string with double quote, I've tested a new macro :
#define STATIC_ASSERT(CONDITION, MSG) \
typedef char static_assert[((void)(MSG), ((CONDITION)?1:-1))]
Using the , comma operator, this macro should accept MSG as a string, and just disregard it. But it will be displayed in case of error, which is the intention.
It works fine on clang, but not of gcc : error: variably modified at file scope.
I'm trying to understand why, and if there is a work around
If you replace the typedef-array-trick with the enum-trick, then you will get something that seems to work with both clang and gcc:
#define CONDITION 1
#define TOKENPASTE(a, b) a ## b // "##" is the "Token Pasting Operator"
#define TOKENPASTE2(a,b) TOKENPASTE(a, b) // expand then paste
#define static_assert(x, msg) enum { TOKENPASTE2(ASSERT_line_,__LINE__) \
= 1 / (msg && (x)) }
static_assert( CONDITION, "This should pass");
static_assert(!CONDITION, "This should fail");
This gives me, with gcc for example, on line 9 of foo.c:
foo.c:9: warning: division by zero [-Wdiv-by-zero]
static_assert(!CONDITION, "This should fail");
^
foo.c:9: error: enumerator value for 'ASSERT_line_9' is not an integer constant
static_assert(!CONDITION, "This should fail");
^~~~~~~~~~~~~
(Here the gcc switch -ftrack-macro-expansion=0 is used, as the extra error messages are not that helpful and just add noise.)
Note that some mangling of the name is still necessary, which you omitted. Here the text ASSERT_line_ is combined with the variable __LINE__. This ensures a unique name, provided:
You don't use it twice on a single line.
You don't use it in header files (or trust to luck).
Your code doesn't happen to use the identifiers like ASSERT_line_9 elsewhere.
For header files, you will need to add somewhere a single word with only identifier characters. For example:
#define static_assert3(x, msg, file) enum { TOKENPASTE2(file,__LINE__) = \
1 / (msg && (x)) }
#define static_assert(x, msg) static_assert3(x, msg, my_header_h_)
If this fails on line 17, gcc will give an error such as:
error: enumerator value for 'my_header_h_17' is not an integer constant
An alternative for the mangling in header files is to replace __LINE__ with __COUNTER__. I've not used it, because it is non-standard and because clang was slow to adopt it. But now it has been in gcc, msvc, and clang for about five years.
You could try the same modification with your typedef-array idea, and replace the comma operator with &&. Then your gcc error changes into a warning. For example, modifying your godbolt example to:
typedef char static_assert_2["hello world!" && (CONDITION) ? 1 : -1];
gives the unwanted warning: variably modified 'static_assert_2' at file scope for gcc.
One-liner
#define STATIC_ASSERT(CONDITION, MSG) { typedef char test[(CONDITION)?1:-1]; (void)(test*) #MSG; } (void)0

Eclipse CDT syntax error for macro using _Generic keyword

I'm using Oxygen with CDT 9.3.0 built-in.
When I use a macro I defined that uses _Generic, all those macro uses are underlined with "syntax error", but the project compiles fine (which is setup to use my makefiles).
After reading a similar so question, and since _Generic begin from C11 possibly not supported by eclipse's code analysis, I tried defining a symbol for my macro definition to empty but it didn't work. (At project settings, C/C++ General->Paths and Symbols->Symbols Tab, GNU C, added symbol CONVERT(...) without a value and added a symbol CONVERT(X), and CONVERT() and CONVERT without a value).
For example my macro is:
#define FIRST_(_1, ...) _1
#define FIRST(...) FIRST_(__VA_ARGS__, _1, _2, _3)
#define CONVERT(...) \
_Generic((FIRST(__VA_ARGS__)), \
char* : toText, \
int : toInt, \
) (__VA_ARGS__)
and usage point, that gives the syntax error:
void* test = CONVERT("testme");
As #ErikW pointed out, _Generic is a C11 feature that Eclipse CDT's parser does not support yet. This bug tracks adding support for it.
(By the way, contributions to Eclipse CDT's C11 support are very welcome!)
It is possible to work around this using macros.
The problem with trying to define another version of the CONVERT(...) macro in "Paths and Symbols" is that the macros defined there are treated as if you wrote them at the very top of your file. A subsequent redefinition in your actual code overwrites the definition from "Paths and Symbols".
I can think of two approaches to go about this:
Approach 1
CDT defines a special macro __CDT_PARSER__ which evaluates to true when it's parsing the code, but false when the code is actually compiled.
You can take advantage of this to define a different version of CONVERT(...) for CDT's purposes:
#ifdef __CDT_PARSER__
#define CONVERT(...)
#else
#define CONVERT(...) \
_Generic((FIRST(__VA_ARGS__)), \
char* : toText, \
int : toInt, \
) (__VA_ARGS__)
#endif
This almost works, but not quite. We still get a syntax error, because this line:
void* test = CONVERT("testme", 42);
will now expand to:
void* test = ;
As you can see, we don't actually want an empty expansion for CONVERT(...). We want an expansion that will parse as a variable's initializer. 0 will work:
#ifdef __CDT_PARSER__
#define CONVERT(...) 0
#else
...
#endif
Approach 2
Instead of defining a different version of CONVERT(...), we could define _Generic(...) itself to be a macro for CDT's purposes.
This time, we can do it in "Paths and Symbols", because there is no redefinition of _Generic(...) in the code that would mess it up.
So let's define a symbol in "Paths and Symbols", with _Generic(...) as the name and an empty value.
Now, this line:
void* test = CONVERT("testme", 42);
will expand to:
void* test = _Generic((FIRST("testme", 42)), \
char* : toText, \
int : toInt, \
) ("testme", 42)
which will in turn expand to:
void* test = ("testme", 42);
which parses (("testme", 42) parses as a parenthesized comma-expression and is thus a valid initializer).
This approach has the advantage that you don't need to modify your actual code, and that it handles all uses of the _Generic macro rather than just the one in CONVERT.
On the other hand, it's possible that for some other uses of the _Generic macro, this particular expansion won't parse. If that's the case, you might be able to come up with a different expansion that will parse for all uses, or else you can go with Approach 1.

Restoring definitions and macros

Is there a way to restore macros in C, so that you can define a new macro, under which name probably other macros are already defined, and redefine it with the previous value?
so that when new defined macros are deleted and eventually redefined macros are resetted to its previous state?
Example:
// a macro parameter used in a library
#define size 10
#include <library/use_size.h>
//here the command/pragma to save the definitions
#define size (100 / sizeof(size_t))
// some use of size ...
//here the command/pragma to reset the definitions
#include <library/allocator_with_size.h>
#undef size
// use size as a variable name
size_t size = 0;
//...
size += 123;
Edit: I do not want to use #undef, because it does not restore old macros. Also, if you have many macros, eg for using them in a X-macro-list (in a long repetitive code/declaration of constant arrays and structs), it looks ugly, if there are many #undef directives.
Ok I researched myself and found the pragmas push_macro and pop_macro, supported by clang, gcc and visual c++. I use clang, so it is no problem to use it. The disadvantage: it does not reduce the line-count if you want to restore multiple macros ¹, but it restores the macros and can be encapsulated:
#pragma push_macro("size")
#define size (100 / sizeof(size_t))
#pragma pop_macro("size")
Notes:
¹ I defined multiple macros and tried to restore them with:
#pragma push_macro("size", "key", "name")
// define them all
#pragma pop_macro("size", "key", "name")
But that is not implemented into the compilers yet. So for each macro there must be a seperate line to do this.

Compile time configuration using if-statements

In the embedded C world, we frequently store configuration details in headers so that a library can be built for a specific task, minimizing overhead and compiled size.
One example would be:
//libnameConf.h
#define LIBNAME_WAVE LIBNAME_A
typedef enum {
LIBNAME_A,
LIBNAME_B,
LIBNAME_C
} libname_wave_t;
//libname.c
double coef_arr_a[100] = {...};
double coef_arr_b[100] = {...};
double coef_arr_c[100] = {...};
if (LIBNAME_WAVE == LIBNAME_A) {
somestruct.waveCoefs = coef_arr_a;
//do other coef_arr_a specific stuff
} else if (LIBNAME_WAVE == LIBNAME_B) {...}
For this particular case we're using an if-statement that the compiler will obviously collapse which is a good thing because we only want a reference to coef_arr_a so that the others won't be compiled into the binary and take up space.
Unfortunately, this yields the warning
warning: comparison between 'enum <anonymous>' and 'enum <anonymous>' [-Wenum-compare]
Is there a better way that avoids this warning?
How about using macros only instead of using variables and enumerations.
//libnameConf.h
#define LIBNAME_A
// #define LIBNAME_B // Uncomment this line and both comment the above line while changing libs.
Then we use several conditional compilation statements like this.
//libname.c
double coef_arr_a[100] = {...};
double coef_arr_b[100] = {...};
#ifdef LIBNAME_A
somestruct.waveCoefs = coef_arr_a;
//do other coef_arr_a specific stuff
#endif
#ifdef LIBNAME_B
somestruct.waveCoefs = coef_arr_b;
#endif
Sounds like you need conditional compilaiton in C but the way you're doing it is not correct. Conditional compilation is a concept of the preprocessor which is run before the compiler. The point of preprocessor is to manipulate the source code before it is fed to the compiler. Since you haven't used any preprocessor conditionals, all the source code is fed to the compiler regardless of your compile-time conditionals. You should definitely use preprocessor conditionals to reduce your binary.

Resources