new preprocessor trick to me - c

(Below code is correct, not create by myself.)
(it is inside the config of a motor board.)
#define BTN_TABLE(X) X(BUTTON, PA1)
#define BTN_X_EXTERNS(A, B) extern Button A;
BTN_TABLE(BTN_X_EXTERNS)
#define BTN_X_ID(A, B) A##_ID
#define BTN_X_ENUM(A, B) BTN_X_ID(A, B),
typedef enum { BTN_TABLE(BTN_X_ENUM) NUM_BOARD_BUTTONS } BoardButtonID;
#define BTN_X_FROM_ENUM(A, B) else if (button_id == BTN_X_ID(A, B)) return &A;
static __forceinline Button* button_from_enum(BoardButtonID button_id) {
if (0) return 0;
BTN_TABLE(BTN_X_FROM_ENUM)
else return 0;
}
I don't get the meaning of if (0) return 0; and else return 0; in above example.
why place the Marco in between these two line?
I think we cannot place anything between if{} , else{} statement.

I think the intent behind this code was as follows:
We have some buttons; currently just one, but eventually there may be many more
Each button needs a corresponding global variable and a value in the BoardButtonID enum
We want a function which given the enum BoardButtonID value returns a pointer to the button's global variable
We want to achieve all this while only listing all buttons once.
#bolov has shown how the code expands. I'll note that one can add more buttons just by changing the definition of the BTN_TABLE macro:
#define BTN_TABLE(X) X(BUTTON, PA1) \
X(ANOTHER_BUTTON, PA2) \
X(YET_ANOTHER_BUTTON, PA3) \
X(OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP, PA4)
The PA1, PA2, ... aren't actually used in this version of the code; maybe they would have been used for something later.
Now you can see the effect (I've reformatted the output):
extern Button BUTTON;
extern Button ANOTHER_BUTTON;
extern Button YET_ANOTHER_BUTTON;
extern Button OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP;
typedef enum {
BUTTON_ID,
ANOTHER_BUTTON_ID,
YET_ANOTHER_BUTTON_ID,
OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP_ID,
NUM_BOARD_BUTTONS
} BoardButtonID;
static __forceinline Button* button_from_enum(BoardButtonID button_id) {
if (0)
return 0;
else if (button_id == BUTTON_ID)
return &BUTTON;
else if (button_id == ANOTHER_BUTTON_ID)
return &ANOTHER_BUTTON;
else if (button_id == YET_ANOTHER_BUTTON_ID)
return &YET_ANOTHER_BUTTON;
else if (button_id == OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP_ID)
return &OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP;
else
return 0;
}
And this makes it clear why the initial if is needed: the macro expansion in button_from_enum has no way to treat the first one specially. So it has to produce an else if for every button, including the first one, and the only way to make that valid is for there to be an if at the beginning. It needs to have a test that always fails, hence 0, and its corresponding "then" clause doesn't matter as it will never execute. The return 0 there may have just been chosen to shut up a compiler warning about the function possibly returning without a value. Of course, the return 0 in the final else clause can be reached, and serves as a default if someone passes a value that doesn't match any button.
You are right that if you put anything else in between the if and else, everything will break.
They could have defined it a little differently and used switch instead, which would have been slightly cleaner. I don't know why they didn't; maybe the compiler generates different code that they didn't like (e.g. a jump table that occupies more code space).
In any event, the resulting set of macros, while clever, are certainly not very easy to maintain. They should probably have considered writing a script instead that would generate the desired code from a simple list of buttons in a text file.
Or, they could have put the Button objects in an array instead of insisting on each one having its own variable. This would go nicely with their enum:
typedef enum {
BUTTON_ID,
ANOTHER_BUTTON_ID,
YET_ANOTHER_BUTTON_ID,
OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP_ID,
NUM_BOARD_BUTTONS
} BoardButtonID;
Button all_the_buttons[NUM_BOARD_BUTTONS];
static __forceinline Button* button_from_enum(BoardButtonID button_id) {
if (button_id < NUM_BOARD_BUTTONS)
return &all_the_buttons[button_id];
else
return NULL;
}
This way still only requires listing the buttons once, and it involves no macros at all.

This is one of the most unreadable pieces of code I have seen.
I personally don't have neither the time, energy or willingness to analyze and figure out these horible macros. So I just dumped the preprocessor output and this is the code presented to the compiler:
extern Button BUTTON;
typedef enum { BUTTON_ID, NUM_BOARD_BUTTONS } BoardButtonID;
static __forceinline Button* button_from_enum(BoardButtonID button_id) {
if (0) return 0;
else if (button_id == BUTTON_ID) return &BUTTON;
else return 0;
}

it is inside the config of a motor board.
That explains the code. It is consistent with code that is generated by other software, rather than by a human. It is generated by some code that configures a software package to some target environment.
The purpose of code like this:
if (0) return 0;
BTN_TABLE(BTN_X_FROM_ENUM)
else return 0;
is to allow the generating code to put any number of else if lines between the if line and the else line. For example, in various circumstances, the generated code might be this:
if (0) return 0;
else return 0;
or this:
if (0) return 0;
BTN_TABLE(BTN_X_FROM_ENUM)
else return 0;
or this:
if (0) return 0;
BTN_TABLE(BTN_X_FROM_ENUM)
BTN_TABLE(BTN_Y_FROM_ENUM)
else return 0;
By using if (0) and else as bookends, the generating code is freed from having to have conditional cases such as “If there are zero conditions, just write return 0;. If there is one condition, write if (condition) return something; else return 0;. If there are multiple conditions, write if (first condition) return something; else if (second condition) return something;… else return 0;.
Instead, the generating code is simply:
Write if (0) return 0;.
For each condition, write an else if line for it (likely in the form of some BTN_TABLE macro use, the definition for which is emitted elsewhere in the generating code).
Write else return 0;.
Thus, while the resulting code is more complicated, the actual generating code is simpler.
I don't get the meaning of if (0) return 0; and else return 0; in above example.
The if (0) is needed simply so that the following lines can be any number of else if statements. The return 0; is never executed and is simply needed to complete the if statement grammatically.
The else return 0; statement provides a default in case none of the conditions are met.
why place the Marco in between these two line?
The generating code emits a macro invocation for every case it determines is needed in the target system.
I think we cannot place anything between if{} , else{} statement.
Of course you can, the else if statements are proper there.

Related

Adding "else" at the end of an if-else statement [duplicate]

Our organization has a required coding rule (without any explanation) that:
if … else if constructs should be terminated with an else clause
Example 1:
if ( x < 0 )
{
x = 0;
} /* else not needed */
Example 2:
if ( x < 0 )
{
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
}
What edge case is this designed to handle?
What also concerns me about the reason is that Example 1 does not need an else but Example 2 does. If the reason is re-usability and extensibility, I think else should be used in both cases.
As mentioned in another answer, this is from the MISRA-C coding guidelines. The purpose is defensive programming, a concept which is often used in mission-critical programming.
That is, every if - else if must end with an else, and every switch must end with a default.
There are two reasons for this:
Self-documenting code. If you write an else but leave it empty it means: "I have definitely considered the scenario when neither if nor else if are true".
Not writing an else there means: "either I considered the scenario where neither if nor else if are true, or I completely forgot to consider it and there's potentially a fat bug right here in my code".
Stop runaway code. In mission-critical software, you need to write robust programs that account even for the highly unlikely. So you could see code like
if (mybool == TRUE)
{
}
else if (mybool == FALSE)
{
}
else
{
// handle error
}
This code will be completely alien to PC programmers and computer scientists, but it makes perfect sense in mission-critical software, because it catches the case where the "mybool" has gone corrupt, for whatever reason.
Historically, you would fear corruption of the RAM memory because of EMI/noise. This is not much of an issue today. Far more likely, memory corruption occurs because of bugs elsewhere in the code: pointers to wrong locations, array-out-of-bounds bugs, stack overflow, runaway code etc.
So most of the time, code like this comes back to slap yourself in the face when you have written bugs during the implementation stage. Meaning it could also be used as a debug technique: the program you are writing tells you when you have written bugs.
EDIT
Regarding why else is not needed after every single if:
An if-else or if-else if-else completely covers all possible values that a variable can have. But a plain if statement is not necessarily there to cover all possible values, it has a much broader usage. Most often you just wish to check a certain condition and if it is not met, then do nothing. Then it is simply not meaningful to write defensive programming to cover the else case.
Plus it would clutter up the code completely if you wrote an empty else after each and every if.
MISRA-C:2012 15.7 gives no rationale why else is not needed, it just states:
Note: a final else statement is not required for a simple if
statement.
Your company followed MISRA coding guidance. There are a few versions of these guidelines that contain this rule, but from MISRA-C:2004†:
Rule 14.10 (required): All if … else if constructs shall be terminated
with an else clause.
This rule applies whenever an if statement is followed by one or more
else if statements; the final else if shall be followed by an else
statement. In the case of a simple if statement then the else
statement need not be included. The requirement for a final else
statement is defensive programming. The else statement shall either
take appropriate action or contain a suitable comment as to why no
action is taken. This is consistent with the requirement to have a
final default clause in a switch statement. For example this code
is a simple if statement:
if ( x < 0 )
{
log_error(3);
x = 0;
} /* else not needed */
whereas the following code demonstrates an if, else if construct
if ( x < 0 )
{
log_error(3);
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
}
In MISRA-C:2012, which supersedes the 2004 version and is the current recommendation for new projects, the same rule exists but is numbered 15.7.
Example 1:
in a single if statement programmer may need to check n number of conditions and performs single operation.
if(condition_1 || condition_2 || ... condition_n)
{
//operation_1
}
In a regular usage performing a operation is not needed all the time when if is used.
Example 2:
Here programmer checks n number of conditions and performing multiple operations. In regular usage if..else if is like switch you may need to perform a operation like default. So usage else is needed as per misra standard
if(condition_1 || condition_2 || ... condition_n)
{
//operation_1
}
else if(condition_1 || condition_2 || ... condition_n)
{
//operation_2
}
....
else
{
//default cause
}
† Current and past versions of these publications are available for purchase via the MISRA webstore (via).
This is the equivalent of requiring a default case in every switch.
This extra else will Decrease code coverage of your program.
In my experience with porting linux kernel , or android code to different platform many time we do something wrong and in logcat we see some error like
if ( x < 0 )
{
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
printk(" \n [function or module name]: this should never happen \n");
/* It is always good to mention function/module name with the
logs. If you end up with "this should never happen" message
and the same message is used in many places in the software
it will be hard to track/debug.
*/
}
Only a brief explanation, since I did this all about 5 years ago.
There is (with most languages) no syntactic requirement to include "null" else statement (and unnecessary {..}), and in "simple little programs" there is no need. But real programmers don't write "simple little programs", and, just as importantly, they don't write programs that will be used once and then discarded.
When one write an if/else:
if(something)
doSomething;
else
doSomethingElse;
it all seems simple and one hardly sees even the point of adding {..}.
But some day, a few months from now, some other programmer (you would never make such a mistake!) will need to "enhance" the program and will add a statement.
if(something)
doSomething;
else
doSomethingIForgot;
doSomethingElse;
Suddenly doSomethingElse kinda forgets that it's supposed to be in the else leg.
So you're a good little programmer and you always use {..}. But you write:
if(something) {
if(anotherThing) {
doSomething;
}
}
All's well and good until that new kid makes a midnight modification:
if(something) {
if(!notMyThing) {
if(anotherThing) {
doSomething;
}
else {
dontDoAnything; // Because it's not my thing.
}}
}
Yes, it's improperly formatted, but so is half the code in the project, and the "auto formatter" gets bollixed up by all the #ifdef statements. And, of course, the real code is far more complicated than this toy example.
Unfortunately (or not), I've been out of this sort of thing for a few years now, so I don't have a fresh "real" example in mind -- the above is (obviously) contrived and a bit hokey.
This, is done to make the code more readable, for later references and to make it clear, to a later reviewer, that the remaining cases handled by the last else, are do nothing cases, so that they are not overlooked somehow at first sight.
This is a good programming practice, which makes code reusable and extend-able.
I would like to add to – and partly contradict – the previous answers. While it is certainly common to use if-else if in a switch-like manner that should cover the full range of thinkable values for an expression, it is by no means guaranteed that any range of possible conditions is fully covered. The same can be said about the switch construct itself, hence the requirement to use a default clause, which catches all remaining values and can, if not otherwise required anyway, be used as an assertion safeguard.
The question itself features a good counter-example: The second condition does not relate to x at all (which is the reason why I often prefer the more flexible if-based variant over the switch-based variant). From the example it is obvious that if condition A is met, x should be set to a certain value. Should A not be met, then condition B is tested. If it is met, then x should receive another value. If neither A nor B are met, then x should remain unchanged.
Here we can see that an empty else branch should be used to comment on the programmer's intention for the reader.
On the other hand, I cannot see why there must be an else clause especially for the latest and innermost if statement. In C, there is no such thing as an 'else if'. There is only if and else. Instead, the construct should formally be indented this way (and I should have put the opening curly braces on their own lines, but I don't like that):
if (A) {
// do something
}
else {
if (B) {
// do something else (no pun intended)
}
else {
// don't do anything here
}
}
Should any standard happen to require curly braces around every branch, then it would contradict itself if it mentioned "if ... else if constructs" at the same time.
Anyone can imagine the ugliness of deeply nested if else trees, see here on a side note. Now imagine that this construct can be arbitrarily extended anywhere. Then asking for an else clause in the end, but not anywhere else, becomes absurd.
if (A) {
if (B) {
// do something
}
// you could to something here
}
else {
// or here
if (B) { // or C?
// do something else (no pun intended)
}
else {
// don't do anything here, if you don't want to
}
// what if I wanted to do something here? I need brackets for that.
}
In the end, it comes down for them to defining precisely what is meant with an "if ... else if construct"
The basic reason is probably code coverage and the implicit else: how will the code behave if the condition is not true? For genuine testing, you need some way to see that you have tested with the condition false. If every test case you have goes through the if clause, your code could have problems in the real world because of a condition that you did not test.
However, some conditions may properly be like Example 1, like on a tax return: "If the result is less than 0, enter 0." You still need to have a test where the condition is false.
Logically any test implies two branches. What do you do if it is true, and what do you do if it is false.
For those cases where either branch has no functionality, it is reasonable to add a comment about why it doesn't need to have functionality.
This may be of benefit for the next maintenance programmer to come along. They should not have to search too far to decide if the code is correct. You can kind of Prehunt the Elephant.
Personally, it helps me as it forces me to look at the else case, and evaluate it. It may be an impossible condition, in which case i may throw an exception as the contract is violated. It may be benign, in which case a comment may be enough.
Your mileage may vary.
Most the time when you just have a single if statement, it's probably one of reasons such as:
Function guard checks
Initialization option
Optional processing branch
Example
void print (char * text)
{
if (text == null) return; // guard check
printf(text);
}
But when you do if .. else if, it's probably one of reasons such as:
Dynamic switch-case
Processing fork
Handling a processing parameter
And in case your if .. else if covers all possibilities, in that case your last if (...) is not needed, you can just remove it, because at that point the only possible values are the ones covered by that condition.
Example
int absolute_value (int n)
{
if (n == 0)
{
return 0;
}
else if (n > 0)
{
return n;
}
else /* if (n < 0) */ // redundant check
{
return (n * (-1));
}
}
And in most of these reasons, it's possible something doesn't fit into any of the categories in your if .. else if, thus the need to handle them in a final else clause, handling can be done through business-level procedure, user notification, internal error mechanism, ..etc.
Example
#DEFINE SQRT_TWO 1.41421356237309504880
#DEFINE SQRT_THREE 1.73205080756887729352
#DEFINE SQRT_FIVE 2.23606797749978969641
double square_root (int n)
{
if (n > 5) return sqrt((double)n);
else if (n == 5) return SQRT_FIVE;
else if (n == 4) return 2.0;
else if (n == 3) return SQRT_THREE;
else if (n == 2) return SQRT_TWO;
else if (n == 1) return 1.0;
else if (n == 0) return 0.0;
else return sqrt(-1); // error handling
}
This final else clause is quite similar to few other things in languages such as Java and C++, such as:
default case in a switch statement
catch(...) that comes after all specific catch blocks
finally in a try-catch clause
Our software was not mission critical, yet we also decided to use this rule because of defensive programming.
We added a throw exception to the theoretically unreachable code (switch + if-else). And it saved us many times as the software failed fast e.g. when a new type has been added and we forgot to change one-or-two if-else or switch. As a bonus it made super easy to find the issue.
Well, my example involves undefined behavior, but sometimes some people try to be fancy and fails hard, take a look:
int a = 0;
bool b = true;
uint8_t* bPtr = (uint8_t*)&b;
*bPtr = 0xCC;
if(b == true)
{
a += 3;
}
else if(b == false)
{
a += 5;
}
else
{
exit(3);
}
You probably would never expect to have bool which is not true nor false, however it may happen. Personally I believe this is problem caused by person who decides to do something fancy, but additional else statement can prevent any further issues.
I'm currently working with PHP. Creating a registration form and a login form. I am just purely using if and else. No else if or anything that is unnecessary.
If user clicks submits button -> it goes to the next if statement... if username is less than than 'X' amount of characters then alert. If successful then check password length and so on.
No need for extra code such as an else if that could dismiss reliability for server load time to check all the extra code.
As this question on boolean if/else if was closed as a duplicate. As well, there are many bad answers here as it relates to safety-critical.
For a boolean, there are only two cases. In the boolean instance, following the MISRA recommendation blindly maybe bad. The code,
if ( x == FALSE ) {
// Normal action
} else if (x == TRUE ) {
// Fail safe
}
Should just be refactored to,
if ( x == FALSE ) {
// Normal action
} else {
// Fail safe
}
Adding another else increases cyclometric complexity and makes it far harder to test all branches. Some code maybe 'safety related'; Ie, not a direct control function that can cause an unsafe event. In this code, it is often better to have full testability without instrumentation.
For truly safety functional code, it might make sense to separate the cases to detect a fault in this code and have it reported. Although I think logging 'x' on the failure would handle both. For the other cases, it will make the system harder to test and could result in lower availability depending on what the second 'error handling' action is (see other answers where exit() is called).
For non-booleans, there may be ranges that are nonsensical. Ie, they maybe some analog variable going to a DAC. In these cases, the if(x > 2) a; else if(x < -2) b; else c; makes sense for cases where deadband should not have been sent, etc. However, these type of cases do not exist for a boolean.

How to solve warning problems?

I am trying to resolve warning issues which is shown as below :
warning: suggest braces around empty body in an 'if' statement
Relevant code:
cdc(.....)
{
//some statements
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t); //Showing warning in this line
if(something)
{
if(..)
{
}
else
{
}
}
else
{
}
}
If I remove ; and adding the braces as below
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t)
{
}
the warning is gone.
What does exactly it means? Is it behaving like an if statement?
Sorry, its confidential code, so I cant share entirely.
If this is your code
if (/* condition */);
/* other code */
Then the other code will ALWAYS be executed.
You probably want the other code to only be executed if the condition is true.
In order to achieve that, you mainly have to delete the ;.
It is widely considered to be best practice to be somewhat generous with the {}, i.e.
if (/* condition */)
{
/* other code */
}
The fact that the warning does not occur after deleting the ; in line
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t); and replacing it with {}
can be explained if it is actually a macro which essentially expands (together with the ; which is NOT part of the macro) to the if();, which earlier versions of your question were mentioning.
The replacement with {} then does exactly what the compiler wanted.
The ENTER_FUNC() is probably meant to be used like
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t) /* delete this ; */
{ /* new {, followed by rest of your function code */
if(something)
{
if(..)
{
}
else
{
}
}
else
{
}
} /* new */
Please excuse that this answer more or less assumes that you made a mistake in your code. Compare the contribution by Scheff, which assumes (also plausibly) that actually you were acting to a more complex design and fully intentionally.
The statement
if (cond) ; else do_something();
or even
if (cond) ; do_something();
might be intended. May be, the ; after if (cond) is a placeholder for something which shall be added later.
Inserting comments
if (cond) /** #todo */ ; else do_something();
or
if (cond) /** #todo */ ; /* and then always */ do_something();
would make it clear to the human reader but not for the compiler which ignores comments completely.
However, the compiler authors suspected high chance that the semicolon was unintendedly set (and can easily be overlooked). Hence, they spent a warning about this and gave a hint how to make the intention clear if there is one:
Use { } instead ; for intendedly empty then-body to come around this warning.
Sample:
#include <stdio.h>
int main()
{
int cond = 1;
if (cond) /** #todo */ ; else printf("cond not met.\n");
if (cond) /** #todo */ ; printf("cond checked.\n");
return 0;
}
Output:
cond checked.
Life demo on ideone
The compiler used on ideone is stated as gcc 6.3.
I must admit that I didn't get the diagnostics of OP.
After the question was edited, the answer does not seem to match the question anymore. Hence, a little update:
The OP states that the
warning: suggest braces around empty body in an 'if' statement
appears for this line of code:
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t); //Showing warning in this line
It seems that the OP was not aware that ENTER_FUNC is (very likely) a macro with an if statement in its replacement text (something like #define ENTER_FUNC(A,B) if (...)). (This is the most imaginable scenario to get this warning for this code.)
Unfortunately, the OP is not willing to show how ENTER_FUNC is defined, nor to prepare an MCVE with the same behavior.
However, the technique to hide an if in a macro is even more questionable – I wouldn't recommend to do so. Imagine the following situation:
cdc(.....)
{
//some statements
ENTER_FUNC(CDC_TRKEY_FC,cdcType_t) // This time, the author forgot the ; or {}
if(something)
{
if(..)
{
}
else
{
}
}
else
{
}
}
The if(something) statement becomes now the body of the hidden if of the ENTER_FUNC() macro which is probably not intended but a bug. The application may now behave wrong in certain situations. By simply looking at the source code, this is probably hard to catch. Only, by single-step debugging and a bit luck, the error can be found.
(Another option would be to expand all macros and check the C code after replacement. C compilers provide usually a pre-process-only option which makes the result of pre-processing visible to human eyes. E.g. gcc -E)
So, the author of ENTER_FUNC built a macro which
causes a compiler warning if macro is used properly
where the warning goes away if macros is used wrong.
IMHO, this is a not-so-lucky design.

macro expansion using flag variables at runtime

if (a==5)
{
#define FLAG 1
}
#ifdef FLAG
{
// Execute this portion else not
}
#endif
I want to use this as flag variable and if the variable is defined(at runtime depending upon condition) then the piece if code in #ifdef shall be executed else not.
If this is not possible in c programming then please suggest me the best way to implement the same.
Which can help in faster execution of code. Also reduced compilation time
1) FLAG is not variable, it is a preprocessor symbol.
2) The preprocessor is running from top to bottom defining the symbols (or undefining them) regardless of your compilable code logic (so of course it can't depend on it), before it is even compiled. So in your example the #ifdef will always work.
3) To achieve the functionality you seem to want, just use a regular if/else statements.
bool flag = false;
if (a == 5)
{
flag = true;
}
if (flag)
{
// [...]
}

Is there a better way to do C style error handling?

I'm trying to learn C by writing a simple parser / compiler. So far its been a very enlightening experience, however coming from a strong background in C# I'm having some problems adjusting - in particular to the lack of exceptions.
Now I've read Cleaner, more elegant, and harder to recognize and I agree with every word in that article; In my C# code I avoid throwing exceptions whenever possible, however now that I'm faced with a world where I can't throw exceptions my error handling is completely swamping the otherwise clean and easy-to-read logic of my code.
At the moment I'm writing code which needs to fail fast if there is a problem, and it also potentially deeply nested - I've settled on a error handling pattern whereby "Get" functions return NULL on an error, and other functions return -1 on failure. In both cases the function that fails calls NS_SetError() and so all the calling function needs to do is to clean up and immediately return on a failure.
My issue is that the number of if (Action() < 0) return -1; statements that I have is doing my head in - it's very repetitive and completely obscures the underlying logic. I've ended up creating myself a simple macro to try and improve the situation, for example:
#define NOT_ERROR(X) if ((X) < 0) return -1
int NS_Expression(void)
{
NOT_ERROR(NS_Term());
NOT_ERROR(Emit("MOVE D0, D1\n"));
if (strcmp(current->str, "+") == 0)
{
NOT_ERROR(NS_Add());
}
else if (strcmp(current->str, "-") == 0)
{
NOT_ERROR(NS_Subtract());
}
else
{
NS_SetError("Expected: operator");
return -1;
}
return 0;
}
Each of the functions NS_Term, NS_Add and NS_Subtract do a NS_SetError() and return -1 in the case of an error - its better, but it still feels like I'm abusing macros and doesn't allow for any cleanup (some functions, in particular Get functions that return a pointer, are more complex and require clean-up code to be run).
Overall it just feels like I'm missing something - despite the fact that error handling in this way is supposedly easier to recognize, In many of my functions I'm really struggling to identify whether or not errors are being handled correctly:
Some functions return NULL on an error
Some functions return < 0 on an error
Some functions never produce an error
My functions do a NS_SetError(), but many other functions don't.
Is there a better way that I can structure my functions, or does everyone else also have this problem?
Also is having Get functions (that return a pointer to an object) return NULL on an error a good idea, or is it just confusing my error handling?
It's a bigger problem when you have to repeat the same finalizing code before each return from an error. In such cases it is widely accepted to use goto:
int func ()
{
if (a() < 0) {
goto failure_a;
}
if (b() < 0) {
goto failure_b;
}
if (c() < 0) {
goto failure_c;
}
return SUCCESS;
failure_c:
undo_b();
failure_b:
undo_a();
failure_a:
return FAILURE;
}
You can even create your own macros around this to save you some typing, something like this (I haven't tested this though):
#define CALL(funcname, ...) \
if (funcname(__VA_ARGS__) < 0) { \
goto failure_ ## funcname; \
}
Overall, it is a much cleaner and less redundant approach than the trivial handling:
int func ()
{
if (a() < 0) {
return FAILURE;
}
if (b() < 0) {
undo_a();
return FAILURE;
}
if (c() < 0) {
undo_b();
undo_a();
return FAILURE;
}
return SUCCESS;
}
As an additional hint, I often use chaining to reduce the number of if's in my code:
if (a() < 0 || b() < 0 || c() < 0) {
return FAILURE;
}
Since || is a short-circuit operator, the above would substitute three separate if's. Consider using chaining in a return statement as well:
return (a() < 0 || b() < 0 || c() < 0) ? FAILURE : SUCCESS;
One technique for cleanup is to use an while loop that will never actually iterate. It gives you goto without using goto.
#define NOT_ERROR(x) if ((x) < 0) break;
#define NOT_NULL(x) if ((x) == NULL) break;
// Initialise things that may need to be cleaned up here.
char* somePtr = NULL;
do
{
NOT_NULL(somePtr = malloc(1024));
NOT_ERROR(something(somePtr));
NOT_ERROR(somethingElse(somePtr));
// etc
// if you get here everything's ok.
return somePtr;
}
while (0);
// Something went wrong so clean-up.
free(somePtr);
return NULL;
You lose a level of indentation though.
Edit: I'd like to add that I've nothing against goto, it's just that for the use-case of the questioner he doesn't really need it. There are cases where using goto beats the pants off any other method, but this isn't one of them.
You're probably not going to like to hear this, but the C way to do exceptions is via the goto statement. This is one of the reasons it is in the language.
The other reason is that goto is the natural expression of the implementation of a state machine. What common programming task is best represented by a state machine? A lexical analyzer. Look at the output from lex sometime. Gotos.
So it sounds to me like now is the time for you to get chummy with that parriah of language syntax elements, the goto.
Besides goto, standard C has another construct to handle exceptional flow control setjmp/longjmp. It has the advantage that you can break out of multiply nested control statements more easily than with break as was proposed by someone, and in addition to what goto provides has a status indication that can encode the reason for what went wrong.
Another issue is just the syntax of your construct. It is not a good idea to use a control statement that can inadvertibly be added to. In your case
if (bla) NOT_ERROR(X);
else printf("wow!\n");
would go fundamentally wrong. I'd use something like
#define NOT_ERROR(X) \
if ((X) >= 0) { (void)0; } \
else return -1
instead.
THis must be thought on at least two levels: how your functions interact, and what you do when it breaks.
Most large C frameworks I see always return a status and "return" values by reference (this is the case of the WinAPI and of many C Mac OS APIs). You want to return a bool?
StatusCode FooBar(int a, int b, int c, bool* output);
You want to return a pointer?
StatusCode FooBar(int a, int b, int c, char** output);
Well, you get the idea.
On the calling function's side, the pattern I see the most often is to use a goto statement that points to a cleanup label:
if (statusCode < 0) goto error;
/* snip */
return everythingWentWell;
error:
cleanupResources();
return somethingWentWrong;
What about this?
int NS_Expression(void)
{
int ok = 1;
ok = ok && NS_Term();
ok = ok && Emit("MOVE D0, D1\n");
ok = ok && NS_AddSub();
return ok
}
The short answer is: let your functions return an error code that cannot possibly be a valid value - and always check the return value. For functions returning pointers, this is NULL. For functions returning a non-negative int, it's a negative value, commonly -1, and so on...
If every possible return value is also a valid value, use call-by-reference:
int my_atoi(const char *str, int *val)
{
// convert str to int
// store the result in *val
// return 0 on success, -1 (or any other value except 0) otherwise
}
Checking the return value of every function might seem tedious, but that's the way errors are handled in C. Consider the function nc_dial(). All it does is checking its arguments for validity and making a network connection by calling getaddrinfo(), socket(), setsockopt(), bind()/listen() or connect(), finally freeing unused resources and updating metadata. This could be done in approximately 15 lines. However, the function has nearly 100 lines due to error checking. But that's the way it is in C. Once you get used to it, you can easily mask the error checking in your head.
Furthermore, there's nothing wrong with multiple if (Action() == 0) return -1;. To the contrary: it is usually a sign of a cautious programmer. It's good to be cautious.
And as a final comment: don't use macros for anything but defining values if you can't justify their use while someone is pointing with a gun at your head. More specifically, never use control flow statements in macros: it confuses the shit out of the poor guy who has to maintain your code 5 years after you left the company. There's nothing wrong with if (foo) return -1;. It's simple, clean and obvious to the point that you can't do any better.
Once you drop your tendency to hide control flow in macros, there's really no reason to feel like you're missing something.
A goto statement is the easiest and potentially cleanest way to implement exception style processing. Using a macro makes it easier to read if you include the comparison logic inside the macro args. If you organize the routines to perform normal (i.e. non-error) work and only use the goto on exceptions, it is fairly clean for reading. For example:
/* Exception macro */
#define TRY_EXIT(Cmd) { if (!(Cmd)) {goto EXIT;} }
/* My memory allocator */
char * MyAlloc(int bytes)
{
char * pMem = NULL;
/* Must have a size */
TRY_EXIT( bytes > 0 );
/* Allocation must succeed */
pMem = (char *)malloc(bytes);
TRY_EXIT( pMem != NULL );
/* Initialize memory */
TRY_EXIT( initializeMem(pMem, bytes) != -1 );
/* Success */
return (pMem);
EXIT:
/* Exception: Cleanup and fail */
if (pMem != NULL)
free(pMem);
return (NULL);
}
It never occurred to me to use goto or do { } while(0) for error handling in this way - its pretty neat, however after thinking about it I realised that in many cases I can do the same thing by splitting the function out into two:
int Foo(void)
{
// Initialise things that may need to be cleaned up here.
char* somePtr = malloc(1024);
if (somePtr = NULL)
{
return NULL;
}
if (FooInner(somePtr) < 0)
{
// Something went wrong so clean-up.
free(somePtr);
return NULL;
}
return somePtr;
}
int FooInner(char* somePtr)
{
if (something(somePtr) < 0) return -1;
if (somethingElse(somePtr) < 0) return -1;
// etc
// if you get here everything's ok.
return 0;
}
This does now mean that you get an extra function, but my preference is for many short functions anyway.
After Philips advice I've also decided to avoid using control flow macros as well - its clear enough what is going on as long as you put them on one line.
At the very least Its reassuring to know that I'm not just missing something - everyone else has this problem too! :-)
Use setjmp.
http://en.wikipedia.org/wiki/Setjmp.h
http://aszt.inf.elte.hu/~gsd/halado_cpp/ch02s03.html
http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch.html
#include <setjmp.h>
#include <stdio.h>
jmp_buf x;
void f()
{
longjmp(x,5); // throw 5;
}
int main()
{
// output of this program is 5.
int i = 0;
if ( (i = setjmp(x)) == 0 )// try{
{
f();
} // } --> end of try{
else // catch(i){
{
switch( i )
{
case 1:
case 2:
default: fprintf( stdout, "error code = %d\n", i); break;
}
} // } --> end of catch(i){
return 0;
}
#include <stdio.h>
#include <setjmp.h>
#define TRY do{ jmp_buf ex_buf__; if( !setjmp(ex_buf__) ){
#define CATCH } else {
#define ETRY } }while(0)
#define THROW longjmp(ex_buf__, 1)
int
main(int argc, char** argv)
{
TRY
{
printf("In Try Statement\n");
THROW;
printf("I do not appear\n");
}
CATCH
{
printf("Got Exception!\n");
}
ETRY;
return 0;
}

Scope Guard in C

I would like to use scope guard in C in order to do profiling.
I would like to know how much time I spend in a function. Here is what I do:
int function() {
tic();
... do stuff ...
if (something)
{
toc();
return 0;
}
toc();
return 1;
}
I need to place a toc statement each time I exit the function. I would like to do that without having to copy paste toc everywhere. Is there a generic way to do that, using a macro or something ?
Also I don't want to change the way the function is called, as there are many functions I have to profile.
Thanks
This doesn't change the way the function is called. Probably not much use if you want to be able to profile every single function, though.
static inline int real_function() {
// previous contents of function(), with no tic or toc
}
int function() {
tic();
int r = real_function();
toc();
return r;
}
As everyone else says: use a profiler, it will save you a lot of effort in the long run. As they don't say: if your platform has one.
If it doesn't, then the easiest might be to say (as a coding rule) that functions must have only one exit point, and that exit point must be via your macro. Then you can manually instrument all your functions with code at entry and exit. Legacy functions with multiple returns can be wrapped up as above.
Also, bear in mind when you're doing anything like this that your compiler can mess you up. You might write this:
tic();
do_something();
int i = something_else();
toc();
return i;
If the compiler determines that something_else has no side-effects, then even though something_else takes significant time, it might turn the code into this:
tic();
do_something();
toc();
return something_else();
And your profile data will under-estimate the time spent in your function. Another reason it's so good to have a real profiler - it can co-operate with the compiler.
You could define a macro like:
#define TOC_RETURN(x) \
do { \
toc(); \
return x; \
} while(0)
which should work anywhere you put it. Then you can automate replacing return *; with TOC_RETURN(*).
Why not use an actual profiling tool, like gprof?
You could just "redefine" return via a macro: (please see Disclaimer)
#include <stdio.h>
void tic() { printf("tic\n"); }
void toc() { printf("toc\n"; }
#define return toc(); return
int foo() {
tic();
return 0;
}
#undef return
int main() {
foo();
return 0;
}
Disclaimer: This can be considered ugly and hacky because:
It won't work for void functions unless you use return;-statements.
It might not be portable/standard, even though it works on MSVC8.
One shouldn't define keywords.
I am very late to the party, but there is another way to do scope guarding in C using the GCC extension cleanup attribute. The cleanup attribute attaches a function to a variable declaration that is run when the variable goes out of scope. Originally intended to perform memory deallocation for dynamically allocated types, it can also be abused as a scope guard.
void cleanup_toc(int *ignored __attribute__((__unused__))) { toc(); }
int function(void) {
tic();
int atexit __attribute__((__cleanup__(cleanup_toc))) = 0;
//... do stuff ...
if (something) {
return 0;
}
return 1;
}
This solution does not use macros, but you can of course wrap this into a macro. For example:
#define CONCATENATE_IMPL(x, y) x ## y
#define CONCATENATE(x, y) CONCATENATE_IMPL(x, y)
#define ATEXIT(f) int CONCATENATE(atexit, __LINE__) __attribute__((__cleanup__(f))) = 0
int function(void) {
ATEXIT(cleanup1); // These are executed in reverse order, i.e.
ATEXIT(cleanup2); // cleanup2 will run before cleanup1.
}
I wouldn't recommend a macro for this. You profile the code just once in a while, and replacing 'return' with some special macro just for that purpose makes code less readable.
Isn't it better to do as follows?
tic();
call_function();
toc();
This automatically handles "all exit points" from the function.
P.S. Why don't you use a profiler?
A real profiler doesn't need you to modify the code, just to compile it with profiling enabled.
Hmm, maybe wrap the function call in a macro (family of macros, really)? Here is one which takes no arguments and returns Retval:
// define the wrapper for name
#define DEFTIMECALL0(Retval,name) \
Retval timed##name() \
{ \
Retval ret;
tic(); \
ret = name(); \
toc(); \
return ret; \
}
You'll need macros for every arity of function calls you make, with a Retval and void returning version.
Edit Maybe there isn't even a point in defining the wrapper function, and better to just have a family of macros (again, for each arity and return type/void versions) which wrap a function call in a tic/toc directly at the callsites
Don't be afraid of instrumenting profilers, which essentially do this for you.

Resources