I'm trying to write some microcontroller code using Texas Instruments examples, and it uses macros everywhere (probably to reduce code size), some of which are surrounded by st(). After reading the comments, I still don't understand why this is necessary or when I should use it:
/*
* This macro is for use by other macros to form a fully valid C statement.
* Without this, the if/else conditionals could show unexpected behavior.
*
* For example, use...
* #define SET_REGS() st( ioreg1 = 0; ioreg2 = 0; )
* instead of ...
* #define SET_REGS() { ioreg1 = 0; ioreg2 = 0; }
* or
* #define SET_REGS() ioreg1 = 0; ioreg2 = 0;
* The last macro would not behave as expected in the if/else construct.
* The second to last macro will cause a compiler error in certain uses
* of if/else construct
*
* It is not necessary, or recommended, to use this macro where there is
* already a valid C statement. For example, the following is redundant...
* #define CALL_FUNC() st( func(); )
* This should simply be...
* #define CALL_FUNC() func()
*
* (The while condition below evaluates false without generating a
* constant-controlling-loop type of warning on most compilers.)
*/
#define st(x) do { x } while (__LINE__ == -1)
Can you give some examples of what would fail when the st is not there? Is there any harm in adding the st where it's not necessary?
What might st stand for? When does the second example with { something } produce compiler errors? Because that's used in some example code, too.
The "do {...} while (0)" is a technique used to avoid some types of problems.
The __LINE__ == -1 probably was used to avoid some compiler warning. __LINE__ == -1 will always be false.
Take a look at this link and it will explain the reason for the "do... while(0)"
http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
Example:
#define a(x) if(x) { printf("%s\n", "OK"); }
int i = 1;
if(0)
a(i);
else
printf("%s\n", "KO");
Will expand to something equivalent to:
if(0)
{
if(x)
{
printf("%s\n", "OK");
}
else printf("%s\n", "KO");
}
However if you define a(x) as:
#define a(x) st(if(x) { printf("%s\n", "OK"); })
it will work, expanding to:
if(0)
{
do
{
if(x)
{
printf("%s\n", "OK");
}
}
while(0);
}
else printf("%s\n", "KO");
Related
I define my exceptions on the command line:
-DEXCEPTION_1=\"first\" -DEXCEPTION_2=\"second\" -DEXCEPTION_3=\"third\"
which I check against a string:
except = 0;
#ifdef EXCEPTION_1
if (! strcmp(EXCEPTION_1, mystring))
{ except = 1;
}
#endif
#ifdef EXCEPTION_2
if (! strcmp(EXCEPTION_2, mystring))
{ except = 1;
}
#endif
#ifdef EXCEPTION_3
if (! strcmp(EXCEPTION_3, mystring))
{ except = 1;
}
#endif
if (except == 1)
{ // do something
}
else
{ // do something else
}
Needless to say, while this works, it is also quite ugly, inflexible and causes redundancy in my code.
Is there a way to append a string to a preprocessor macro variable?
I would like to get something like this (the problem of course is that #append does not exist):
#ifdef EXCEPTION_1 #append EXCEPTIONS if (! strcmp(EXCEPTION_1, mystring)) { except = 1; }
#ifdef EXCEPTION_2 #append EXCEPTIONS if (! strcmp(EXCEPTION_2, mystring)) { except = 1; }
#ifdef EXCEPTION_3 #append EXCEPTIONS if (! strcmp(EXCEPTION_3, mystring)) { except = 1; }
Then I could just use EXCEPTIONS in the code and it would work with all possible permutations of exceptions.
In other words I want to append a string to a macro variable - is it possible?
You can have chains of defines, but it won't look much better:
#ifdef EXCEPTION_1
#define EXCEPTIONS1 if (! strcmp(EXCEPTION_1, mystring)) { except = 1; }
#else
#define EXCEPTIONS1
#endif
#ifdef EXCEPTION_2
#define EXCEPTIONS2 EXCEPTIONS1 if (! strcmp(EXCEPTION_2, mystring)) { except = 1; }
#else
#define EXCEPTIONS2 EXCEPTIONS1
#endif
// etc
Again, not much better.
And you really shouldn't define macros with open if's. It allows weird interactions like if(cond) EXCEPTIONS1 else cout<<"error"; -- that won't do what you expect because EXCEPTIONS1 is a plain if and will gobble up the else branch.
The typical way of writing macros with code blocks is to wrap the whole thing in a do{...}while(0) (note no ending ;).
Checkout the token stringification and concatenation section here
It might help some. In general, it would seem easier to use your command line macro to populate a table and have a macro that simply expands to a loop that checks the successive entries of that table to set the except flag.
For instance, save the following as silly.c and compile with cc -DEX1=\"hello\"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct Except {
const char* key;
int flag;
};
struct Except table[] = {
#if defined(EX1)
{EX1,1},
#endif
{NULL,0}
};
#define CHECKEX(mys,rv) { rv = 0;for(int i=0;table[i].key!=0;i++) \
if (strcmp(table[i].key,(mys))==0) \
rv = 1; \
}
int main()
{
int rv;
CHECKEX("hello",rv);
if (rv)
printf("Got an hello\n");
else printf("Got nothing\n");
return 0;
}
Simply add more "blocks" to the table as needed. Just a suggestion of course.
You can convert a macro argument to a string:
#define STR(x) #x
STR(hello) --> "hello"
And you can concatenate string literals by just writing them next to each other:
"123" "abc" --> "123abc"
Or create a macro:
#define CONCAT(a, b) a b
CONCAT("hello", " world!") --> "hello world!"
You can use ## to concatenate string to macros. Use an index and use the conditions only to set the index. Then at the end you can concatenate the index with your macro EXCEPTION. like,
define a macro like #define append(name) name ## counter
this will in turn give you name as name1 if counter is 1
Now you can define different append macros to come with the result in a single variable name
I would like to force a functions parameters to accept only specific definitions. For example, consider #define OUTPUT 1, #define INPUT 0 and void restrictedFunction(int parameter); .
How would I force restrictedFunction(int parameter) to accept only OUTPUT or INPUT?
I would also like to take into consideration that another definition may have the same value, for example, #define LEFT 1 and #define RIGHT 0.
So in this case I would like restrictedFunction(int parameter) to be able to accept only OUTPUT and INPUT specifically.
typedef enum { INPUT = 0, OUTPUT = 1 } IO_Type;
void restrictedFunction(IO_Type parameter) { ... }
It doesn't absolutely force the use of the values (the compiler will let someone write restrictedFunction(4)), but it is about as good as you'll get.
If you truly want to force the correct type, then:
typedef enum { INPUT = 0, OUTPUT = 1 } IO_Type;
typedef struct { IO_Type io_type } IO_Param;
void restrictedFunction(IO_Param parameter) { ... }
In C99 or later, you could call that with:
restrictedFunction((IO_Param){ INPUT });
This is a compound literal, creating a structure on the fly. It is not entirely clear that the structure type really buys you very much, but it will force the users to think a little and may improve the diagnostics from the compiler when they use it wrong (but they can probably use restrictedFunction((IO_Param){ 4 }); still).
What this means is that your restrictedFunction() code should be ready to validate the argument:
void restrictedFunction(IO_Type io_type)
{
switch (io_type)
{
case INPUT:
...do input handling...
break;
case OUTPUT:
...do output handling...
break;
default:
assert(io_type != INPUT && io_type != OUTPUT);
...or other error handling...
break;
}
}
You could use an enum.
typedef enum TrafficDirection { INPUT = 0, OUTPUT = 1 } TrafficDirection;
restrictedFunction(TrafficDirection direction);
of course, this isn't perfect. You can still pass any int to it as long as you use a cast.
restrictedFunction((TrafficDirection) 4);
You don't get quite as much protection as you might like, but you can do:
enum func_type { INPUT, OUTPUT };
void restrictedFunction( enum func_type parameter );
You can use a wrapper to validate the argument:
#define restrictedFunction(x) do { \
static_assert((x) == INPUT || (x) == OUTPUT); \
assert(!strcmp(#x, "INPUT") || !strcmp(#x, "OUTPUT")); \
restrictedFunction(x); \
} while(0)
Notes:
This assumes restrictedFunction() returns a void. If it returns a value which you actually use, you'll need something like gcc's compound statement http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html. Or--better--you can use BUILD_BUG_ON_ZERO (see What is ":-!!" in C code?), which I keep forgetting about, because it doesn't seem to work with C++.
The do ... while(0) is to "swallow the semi-colon"; not really relevant here.
static_assert() is a compile-time assert; there are many variants available. Here is a link to one, https://stackoverflow.com/a/9059896/318716, if you don't have your own handy.
assert() is the standard run-time assert.
With gcc 4.1.2, and my version of static_assert(), you can replace the run-time assert() with a compile-time assert when the two !strcmp()'s are replaced with ==; see example below. I haven't tested this with other compilers.
x is only used once in the macro expansion, since the first four references are only used at compile-time.
When your actually define your function, you'll have to add parentheses to disable the macro expansion, as in:
void (restrictedFunction)(int x){ ... }
Also, if your code has a special case (whose code doesn't?) where you need to call restrictedFunction() with the argument foo, you'll need to write:
(restrictedFunction)(foo);
Here is a complete example, which puts a wrapper around the standard library function exit():
#include <stdlib.h>
#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum{EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
#define ASSERTM(e,m) enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
#define exit(x) do { \
ASSERTM((x) == EXIT_SUCCESS || (x) == EXIT_FAILURE, value); \
ASSERTM(#x == "EXIT_SUCCESS" || #x == "EXIT_FAILURE", symbol); \
exit(x); \
} while(0)
int main(void) {
exit(EXIT_SUCCESS); // good
exit(EXIT_FAILURE); // good
exit(0); // bad
exit(3); // doubly bad
}
If I try to compile it, I get:
gcc foo.c -o foo
foo.c: In function 'main':
foo.c:17: error: enumerator value for 'symbol_ASSERT_line_17' is not an integer constant
foo.c:18: warning: division by zero
foo.c:18: error: enumerator value for 'value_ASSERT_line_18' is not an integer constant
foo.c:18: error: enumerator value for 'symbol_ASSERT_line_18' is not an integer constant
Is it possible to write a macro for the following function:
char *sent_same_text(char *txt)
{
return txt;
}
I tried
#define sent_same_text(txt) return(txt);
but getting compilation error.
Simply do:
#define sent_same_text(txt) (txt)
You only need return for functions. A macro is different in that it is a literal string insertion into your code. Make sure you have the parentheses around txt.
A return statement in a macro will return from the function that "calls" the macro. Function-like macros are shorthand for generating the same code multiple times. They are not actual function calls.
Here's an example of why you might put a return in a macro:
/* do-while() loop is a trick to let you define multi-statement macros and */
/* call them like functions. Note the lack of trailing ';' */
#define ERROR(msg) do{ fprintf(stderr, (msg)); errorCount++; return -1; }while(0)
/* foo() returns 0 or success or -1 on failure */
int foo(int x, int y){
if ( x < 10 )
{
ERROR("x is out of range\n");
}
if ( y < 20 )
{
ERROR("y is out of range\n");
}
doSomething(x,y);
return 0;
}
Calling foo with x = 25 would result in a return of -1, and the message "x is out of range" being printed.
Not saying that is good style, but hopefully illustrates how a return in a macro is different from a return in a function.
#define sent_same_text(text) (text)
If I use the macro:
#define AND
in the following way:
if(...)
{
...
}
elseANDif(...)
{
...
}
What output does the preprocessor produce?
Edit:
I intend to use:
#define TEST(params) if(...){...}else
the ... in if(...) is a complicated expression using params
the ... in {...} performs some operations & is independent of params
#define AND
TEST(x1) AND TEST(x2)
{
//the code for the final else
}
Is the AND helping here or can I do without it?
No, this isn't going to work as you expect. And you can test what the preprocessor does by running your code through cpp.
eliben#eliben-desktop:~/temp$ cat z.c
#define AND
if(...)
{
...
}
elseANDif(...)
{
...
}
eliben#eliben-desktop:~/temp$ cpp z.c
# 1 "z.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "z.c"
if(...)
{
...
}
elseANDif(...)
{
...
}
The technical reason is that when cpp expands macros it looks for a complete identifier token matching this macro's name. I.e. in your case, it looks for the identifier AND. However when it parses the code it doesn't find such an identifier. It finds elseANDif which is quite a different identifier. It has no way to break elseANDif into constituents, and that's a good thing because otherwise macros would work very badly. Imagine:
const int FUSIONDEBUG = 5;
Whatever that means, in real C code this would break awfully, since NDEBUG is almost always defined in production code to be empty (google on what NDEBUG means).
Regarding your edit, the best advice I can give you on such matters is DON'T DO IT. (ab)Using macros like this may appear at first to make the code more readable, but in the long term it makes it much less readable, with the added peril that macros are tricky to get perfectly right and with certain combination of tokens can blow up on you badly.
So you can definitely do without the AND as well as without the TEST altogether.
This:
#define TEST(condn) if(...){...}else
is nonsense; what do you expect the ellipses (...) to do!?
the example usage you gave would expand to
if(...){...} else if(...){...}else
{
//the code for the final else
}
which is patently nonsense; where is the condn argument used?. Either way whatever you really intended the AND has no effect other than dummy readability. If you are trying to invent a new language, the C preprocessor is not the way to do this. I can see no advantage to what you appear to be trying to achieve over more straightforward code.
If you intended:
#define TEST(condn) if(condn){/*some code*/}else
then how is the resultant:
if(a==b){/*some code*/} else if(b==c){/*some code*/}else
{
//the code for the final else
}
better than:
if(a==b || b==c)
{
/*some code*/
}
else
{
//the code for the final else
}
where /*some code*/ is not unnecessarily duplicated?
Note that here the single condition chained by || is equivalent to your multiple conditions chained by else if, so even if you use the TEST macro, there is no need to use it that way when:
TEST( a==b || b==c)
{
//the code for the final else
}
will suffice.
Macros are often ill-advised at the best of times, but you have chosen a particularly prime example of macro abuse! Consider for example how you might debug such code in a source-level debugger.
The short answer to your question is "yes". You can certainly do what you are suggesting. Here is a basic, working example:
#include <stdio.h>
#define AND
#define TEST(params) if (!params) { printf(#params " was false\n"); } else
int main(int argc, char ** argv)
{
int param_1 = 1;
int param_2 = 0;
TEST(param_1) AND TEST(param_2)
{
printf("success!\n");
}
}
After macro expansion, the code would essentially look like this:
int main(int argc, char ** argv)
{
int param_1 = 1;
int param_2 = 0;
if (!param_1) { printf("param_1 was false\n"); } else
if (!param_2) { printf("param_2 was false\n"); } else
{
printf("success!\n");
}
}
As pointed out by others, doing something like this is questionable because it messes with the way people read code and can make future debugging difficult. In a case such as this, I would definitely recommend using a function call if at all possible. This is the approach that Secure recommends in his comment:
int test_parameters(int params)
{
if (!params) { printf("bad parameters"); return 0; }
else { return 1; }
}
int main(int argc, char ** argv)
{
int param_1 = 1;
int param_2 = 0;
if (test_parameters(param_1) && test_parameters(param_2))
{
printf("success!\n");
}
}
This question already has answers here:
Why use apparently meaningless do-while and if-else statements in macros?
(9 answers)
Closed 2 years ago.
I've been seeing that expression for over 10 years now. I've been trying to think what it's good for. Since I see it mostly in #defines, I assume it's good for inner scope variable declaration and for using breaks (instead of gotos.)
Is it good for anything else? Do you use it?
It's the only construct in C that you can use to #define a multistatement operation, put a semicolon after, and still use within an if statement. An example might help:
#define FOO(x) foo(x); bar(x)
if (condition)
FOO(x);
else // syntax error here
...;
Even using braces doesn't help:
#define FOO(x) { foo(x); bar(x); }
Using this in an if statement would require that you omit the semicolon, which is counterintuitive:
if (condition)
FOO(x)
else
...
If you define FOO like this:
#define FOO(x) do { foo(x); bar(x); } while (0)
then the following is syntactically correct:
if (condition)
FOO(x);
else
....
It is a way to simplify error checking and avoid deep nested if's. For example:
do {
// do something
if (error) {
break;
}
// do something else
if (error) {
break;
}
// etc..
} while (0);
It helps to group multiple statements into a single one so that a function-like macro can actually be used as a function. Suppose you have:
#define FOO(n) foo(n);bar(n)
and you do:
void foobar(int n) {
if (n)
FOO(n);
}
then this expands to:
void foobar(int n) {
if (n)
foo(n);bar(n);
}
Notice that the second call bar(n) is not part of the if statement anymore.
Wrap both into do { } while(0), and you can also use the macro in an if statement.
It is interesting to note the following situation where the do {} while (0) loop won't work for you:
If you want a function-like macro that returns a value, then you will need a statement expression: ({stmt; stmt;}) instead of do {} while(0):
#include <stdio.h>
#define log_to_string1(str, fmt, arg...) \
do { \
sprintf(str, "%s: " fmt, "myprog", ##arg); \
} while (0)
#define log_to_string2(str, fmt, arg...) \
({ \
sprintf(str, "%s: " fmt, "myprog", ##arg); \
})
int main() {
char buf[1000];
int n = 0;
log_to_string1(buf, "%s\n", "No assignment, OK");
n += log_to_string1(buf + n, "%s\n", "NOT OK: gcc: error: expected expression before 'do'");
n += log_to_string2(buf + n, "%s\n", "This fixes it");
n += log_to_string2(buf + n, "%s\n", "Assignment worked!");
printf("%s", buf);
return 0;
}
Generically, do/while is good for any sort of loop construct where one must execute the loop at least once. It is possible to emulate this sort of looping through either a straight while or even a for loop, but often the result is a little less elegant. I'll admit that specific applications of this pattern are fairly rare, but they do exist. One which springs to mind is a menu-based console application:
do {
char c = read_input();
process_input(c);
} while (c != 'Q');