I am trying to write #define for ASSERT() using __VA_ARGS.
(This code is for an embedded processor which doesn't support all libc functions).
My source code is like this:
ASSERT(msg == NULL)
ASSERT in header file:
#define ASSERT(...) if(__VA_ARGS__) { printf("[ASSERT ERROR]" __VA_ARGS__ "\n"); }
The preprocessor output is like this, which results compilation error.
if(msg == NULL) { printf("[ASSERT ERROR]" msg == NULL "\n"); }
How do I fix the #define to get rid of compilation errors while keeping the code logically correct?
There's no reason for this to be a variadic macro, at least not with telling us more information about what exactly you're trying to do. A simple one-argument macro using the stringizing operator # will do the trick nicely:
#define ASSERT(x) if(x); else printf("[ASSERT ERROR] " #x "\n")
Also note that I omitted the semicolon at the end and wrote it as if(x); else instead of if(!(x)), so that all of the following code fragments compile correctly as you'd expect, or produce a compiler error as you'd expect:
// #1 - this must be an error, no semicolon
ASSERT(x)
// #2 - this must also be an error
ASSERT(x)
else
/*stuff*/ ;
// #3 - the else must go with the first if, not the inner if inside the macro
// expansion
if (x)
ASSERT(y);
else
/*stuff*/ ;
Your original macro definition fails test #3 above.
Related
For example:
int main()
{
fun();//calling a fun
}
void fun(void)
{
#if 0
int a = 4;
int b = 5;
#endif
}
What is the size of the fun() function? And what is the total memory will be created for main() function?
Compilation of a C source file is done in multiple phases. The phase where the preprocessor runs is done before the phase where the code is compiled.
The "compiler" will not even see code that the preprocessor has removed; from its point of view, the function is simply
void fun(void)
{
}
Now if the function will "create memory" depends on the compiler and its optimization. For a debug build the function will probably still exist and be called. For an optimized release build the compiler might not call or even keep (generate boilerplate code for) the function.
Compilation is split into 4 stages.
Preprocessing.
Compilation.
Assembler.
Linker
Compiler performs preprocessor directives before starting the actual compilation, and in this stage conditional inclusions are performed along with others.
The #if is a conditional inclusion directive.
From C11 draft 6.10.1-3:
Preprocessing directives of the forms
#if constant-expression new-line groupopt
#elif constant-expression new-line groupopt
check whether the controlling constant expression evaluates to nonzero.
As in your code #if 0 tries to evaluate to nonzero but remains false, thereby the code within the conditional block is excluded.
The preprocessing stage can be output to stdout with -E option:
gcc -E filename.c
from the command above the output will give,
# 943 "/usr/include/stdio.h" 3 4
# 2 "filename.c" 2
void fun(void)
{
}
int main()
{
fun();
return 0;
}
As we can see the statements with the #if condition are removed during the preprocessing stage.
This directive can be used to avoid compilation of certain code block.
Now to see if there is any memory allocated by the compiler for an empty function,
filename.c:
void fun(void)
{
}
int main()
{
fun();
return 0;
}
The size command gives,
$ size a.out
text data bss dec hex filename
1171 552 8 1731 6c3 a.out
and for the code,
filename.c:
void fun(void)
{
#if 0
int a = 4;
int b = 5;
#endif
}
int main()
{
fun();
return 0;
}
The output of size command for the above code is,
$ size a.out
text data bss dec hex filename
1171 552 8 1731 6c3 a.out
As seen in both cases memory allocated is same by which can conclude that the compiler does not allocate memory for the block of code disabled by macro.
According to Gcc reference:
The simplest sort of conditional is
#ifdef MACRO
controlled text
#endif /* MACRO */
This block is called a conditional group. controlled text will be
included in the output of the preprocessor if and only if MACRO is
defined. We say that the conditional succeeds if MACRO is defined,
fails if it is not.
The controlled text inside of a conditional can include preprocessing
directives. They are executed only if the conditional succeeds. You
can nest conditional groups inside other conditional groups, but they
must be completely nested. In other words, ‘#endif’ always matches the
nearest ‘#ifdef’ (or ‘#ifndef’, or ‘#if’). Also, you cannot start a
conditional group in one file and end it in another.
Even if a conditional fails, the controlled text inside it is still
run through initial transformations and tokenization. Therefore, it
must all be lexically valid C. Normally the only way this matters is
that all comments and string literals inside a failing conditional
group must still be properly ended.
The comment following the ‘#endif’ is not required, but it is a good
practice if there is a lot of controlled text, because it helps people
match the ‘#endif’ to the corresponding ‘#ifdef’. Older programs
sometimes put MACRO directly after the ‘#endif’ without enclosing it
in a comment. This is invalid code according to the C standard. CPP
accepts it with a warning. It never affects which ‘#ifndef’ the
‘#endif’ matches.
Sometimes you wish to use some code if a macro is not defined. You can
do this by writing ‘#ifndef’ instead of ‘#ifdef’. One common use of
‘#ifndef’ is to include code only the first time a header file is
included.
I am readin linux sources and notice statements like
if (0) {
....
}
What is this magic about?
Example: http://lxr.free-electrons.com/source/arch/x86/include/asm/percpu.h#L132
In this particular macro you're referring to:
132 if (0) { \
133 pao_T__ pao_tmp__; \
134 pao_tmp__ = (val); \
135 (void)pao_tmp__; \
136 } \
the if (0) { ... } block is a way of "using" val without actually using it. The body of this block of code will be evaluated by the compiler, but no code will actually be generated, as an if (0) should always be eliminated - it can never run.
Note that this is a macro. As such, var and val may be of any type - the preprocessor doesn't care. pao_T__ is typedefed to typeof(var). As Andy Shevchenko pointed out, this block of code exists to ensure that val and var are type-compatible, by creating a variable of the same type as var, and assigning val to it. If the types weren't compatible, this assignment would generate a compiler error.
In general, many of the Linux kernel header files should be considered black magic. They are an interesting example of the meta programming that one can do with the C preprocessor, usually for the sake of performance.
I'm using GCC (correction) SDCC with the Eclipse IDE to compile C code for an 8051 architecture embedded target. I need to insert a few NOPs for timing, and I can't get the compiler to accept inline assembly code.
With __asm__ ("; This is a comment\nlabel:\n\tnop"); (as suggested below) or variations I get warning 112: function '__asm__' implicit declaration and then error 101: too many parameters, as if I'm trying to call an undeclared function. I've tried all other options in the SDCC manual section 3.14 also. __asm ... __endasm gives a syntax error on __asm, same with a single underbar, and combinations of whitespace, newlines, or the same line don't help.
If I'm piecing together the command line from the Makefile correctly (without the #include path), the CFLAGS on the SDCC command line are:
-Wp,-MD,$(#:%.rel=%.d),-MT,$#,-MP --disable-warning 110 -Wa,-p --model-medium
Moved from comment
In the sources of SDCC 3.1.0's lexer, I see that both _asm/_endasm and __asm/__endasm are supported. I haven't noticed yet support for __asm("string") in the parser yet.
Also in the lexer's code, the lexing type of the inline assembly token "blob" gets changed to CPP_ASM only if a property called preproc_asm is set to 0, as can be seen in sdcc/support/cpp/libcpp/lex.c:1900.
result->type = CPP_NAME;
{
struct normalize_state nst = INITIAL_NORMALIZE_STATE;
result->val.node.node = lex_identifier (pfile, buffer->cur - 1, false,
&nst);
warn_about_normalization (pfile, result, &nst);
}
/* SDCC _asm specific */
/* handle _asm ... _endasm ; */
if (result->val.node.node == pfile->spec_nodes.n__asm || result->val.node.node == pfile->spec_nodes.n__asm1)
{
if (CPP_OPTION (pfile, preproc_asm) == 0)
{
comment_start = buffer->cur;
result->type = CPP_ASM;
_sdcpp_skip_asm_block (pfile);
/* Save the _asm block as a token in its own right. */
_sdcpp_save_asm (pfile, result, comment_start, result->val.node.node == pfile->spec_nodes.n__asm);
}
result->flags |= ENTER_ASM;
}
else if (result->val.node.node == pfile->spec_nodes.n__endasm || result->val.node.node == pfile->spec_nodes.n__endasm1)
{
result->flags |= EXIT_ASM;
}
/* Convert named operators to their proper types. */
else if (result->val.node.node->flags & NODE_OPERATOR)
{
result->flags |= NAMED_OP;
result->type = (enum cpp_ttype) result->val.node.node->directive_index;
}
break;
The solution was to add #pragma preproc_asm - (or +) at the top of the file and to use the multiline __asm/__endasm blocks.
this link: http://www.crossware.com/smanuals/c8051/_t243.html
has this to say about inline assembly code
Assembler code can be embedded into your C source code in two ways:
using the #asm/#endasm preprocessor directives
using the _asm keyword
The pre-processor directives #asm and #endasm allow assembler code to be included anywhere within the C source code file, the only restriction being that it cannot be positioned within an expression. All lines between #asm and #endasm are passed straight through unmodified to the intermediate file processed by the assembler and so all of the rules for the cross assembler source code are supported.
The pre-processor directives #if, #ifdef, #ifndef, #else, #elif and #endif are valid between #asm and #endasm and so can be used to maintain the assembler code if required.
The _asm keyword can only be used within functions. It is used with following syntax:
_asm();
The string constant is passed straight through unmodified as a single line to the intermediate file processed by the assembler. Each should therefore be a valid line of assembler code.
One advantage of the _asm syntax is that it is subject to token replacement by the C preprocessor. Therefore the statement can be generated by a series of macros.
Also with the _asm syntax, the compiler supports a special construct to enable easy access to C variables. If the variable name is placed in the string contant within curly braces, the compiler replaces the variable name (and the curly braces) with the appropriate substring depending upon the location of the variable. See the following sections for more details.
The compiler generates upper case mnemonics and so if lower case is chosen for the in-line assembler code it can be clearly distinguished from the compiler generated code in the list file.
however, the correct format is: '_asm(" nop");' because a mnemonic assembly instruction cannot be the first thing on a line (that privilege is for labels)
Hi I have been trying to port LWIP to a new arm device. When compiling the code i get the error message:
"lwip/lwip-1.4.0/src/include/lwip/memp_std.h:35:23: error: expected ')' before numeric constant"
When I go to this file this and below this several similar macros is what I find on that line:
LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB")
If I remove the need for this macro with a define to deactivate the RAW functionality the error moves to the next LWIP_MEMPOL() macro.
The define it seems to want to put a ')' in front of is defined as this:
#define MEMP_NUM_RAW_PCB 1
The RAW_PCB is not defined but is "combined with MEMP_" to create an element in an enum.
I have tried to complie the whole ting with the -E option to get human redable object files and see if i can find any open '(' around the areas where MEMP_RAW_PCB apears and the substitution of MEMP_NUM_RAW_PCB to 1 but I have not found any by manual inspection yet.
Are there any suggestions on what can be going on here or what more I can do or look for to find the cause of the error?
I should maybe add that so far I don't call on any of the LWIP code from main() or any of the functions used in main().
I solved it with:
#ifndef MEMP_STD_H_
#define MEMP_STD_H_
... // memp_std.h codes ...
#endif //#ifndef MEMP_STD_H_
The error suggests you have unbalanced parentheses. The code you have provided thus far does not indicate where this problem is, but since ) is expected, it probably means the error is actually in the lines of code preceding the one you have shown.
Examine the code preceding the line you have shown (perhaps after using gcc -E) to check to see if all the parentheses are balanced.
If you're defining it with the dash-D option, it will generate the 1 by default, e.g.:
gcc -D 'MAX(A,B) ((A) < (B)? (B) : (A))' ...
Generates:
#define MAX(A,B) ((A) < (B)? (B) : (A)) 1
And you get the error: expected ‘)’ before numeric constant message at the line where the substitution occurs because of that trailing 1, e.g.:
int maxval = MAX(i,j);
// generates: int maxval = ((i) < (j)? (j) : (i)) 1;
Conversely, if you use the assignment operator to explicitly define the value, it will generate it the way you expected. E.g.:
int maxval = MAX(i,j);
// generates: int maxval = ((i) < (j)? (j) : (i));
the assert() function can print the error and where the error happens, but it will also abort the function.
I want to have a assert() function without aborting. I only hope to print the error, the name of the file where error happens, etc.
is there such a API or source snippets in C?
thanks!
Cunit has an assert that will either be fatal (quits) or not (will continue).
http://cunit.sourceforge.net/doc/writing_tests.html#tests
So if I'm reading this right, your question is basically "How do I print the file name and line number?"
Simple, use
__FILE__, __LINE__
If you want, create your own macro like
#define MY_ASSERT(x) if(x) printf("Assertion! Line: %d File: %s \n", __LINE__, __FILE__)
THere are other useful predefined macros too. http://gcc.gnu.org/onlinedocs/gcc-3.1/cpp/Standard-Predefined-Macros.html
First of all lets see what assert is
the documentation says
assert() is implemented as a macro
and now lets see the actual implementation of assert
something like this
((x = 0) ? (void) (0) : __assert_fail ("x = 0", "t.c", 9, __PRETTY_FUNCTION__));
well in your case you may not want the expression below
__assert_fail ("x = 0", "t.c", 9, __PRETTY_FUNCTION__))
now what we can do here now is
something like this
#define MY_ASSERT(expr) \
(expr ? (void) (0) : printf("something"));
int main(int argc, char *argv[]){
MY_ASSERT(argc == 0)
}
hope this helps
This is called an exception, and it is a construct that is available in languages like C++ with an optimized implementation. With exceptions, you can exit any function anywhere you want, and end up anywhere up the call stack, without a single memory leak. Of course, this will require you code to be exception safe.
In C, you'd need to hack around with goto, setjmp, longjmp, which would basically be a bad version of C++ exceptions.
See e.g. http://en.cppreference.com/w/cpp/language/exceptions