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 pro
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;