I am checking the input arguments provided and if it is not in the range specified, it should exit from the function. Suppose I have called a function, Func(arg)
. If arg
is not in the specified range, the function should return to main()
.
The code sample is as follows:
#define check_param(expr) ((expr) ? (void)0U : exit(3))
void Func(int arg)
{
check_param(arg);
...
...
}
int main()
{
...
Func(10);
...
return 0;
}
If I use exit()
, it will exit the whole program. I want to return to main()
and execute further instructions. I can't use return
as it is a statement. What can be used in place of exit(3)
?
The above definition is used for both type of functions (void
and int
type).
CodePudding user response:
Do not hide the return
, that's just asking for trouble. Simply replace this part:
#define check_param(expr) ((expr) ? (void)0U : exit(3))
void Func(int arg)
{
check_param(arg);
with this:
// suggestion: return 0 on success, or error code
int Func(int arg)
{
if (!arg) return 3; // error code
...
return 0; // no error
}
Using funny macros does not make the code easier to read, and they can be a real head-ache when debugging.
CodePudding user response:
You do not need to use only an expression as the replacement sequence for a macro. It can be a statement (or part of one), such as:
#define check_param(expr) if (!(expr)) return
Since you want the macro to work in functions that return void
and in other functions, we need to give it a way to have a matching return
statement, one that either does or does not give a return value, as desired. We can do this with another parameter:
#define check_param(expr, value) if (!(expr)) return value
Then the macro can be used:
check_param(arg,); // In function that returns void, value is blank.
check_param(arg, -1); // In other functions, value is not blank.
Note that in return value
, value
is not in parentheses. It is usual to enclose macro arguments in parentheses to avoid precedence issues, but that cannot work here because we need return value
to work when value
is blank, and return ();
would cause a syntax error.
Finally, when defining a macro as a statement, there is an idiom to wrap it in a do-while statement so that it acts grammatically like an ordinary statement:
#define check_param(expr, value) do if (!(expr)) return value; while (0)
Note that, in the original if
form, if the macro invocation happens to be followed by an else
, like this:
if (A)
check_param(arg, value);
else
MyRoutine(arg);
then the else
would be associated with the if
resulting from the check_param
macro instead of with the if (A)
. By wrapping the macro in do … while
, we prevent this sort of undesired interpretation.
CodePudding user response:
- I do not see any use of such a macro (maybe to make the code more difficult to read)
- I would use statements, not expressions.
This Macro will work both for void
(second macro parameter blank after comma) and non void
functions. cond
and retval
can be expressions objects or constants. retval
does not have to be in parentheses as it is normally in macros because there are no other operations in this statement.
#define check(cond, retval) do{if(!(cond)) return retval;}while(0)
int foo(int x)
{
check(x == 2, x * 2);
/* ... */
return something;
}
void bar(const char *s1, const char *s2)
{
check(!strcmp(s1,s2), );
}
https://godbolt.org/z/hY9rKe4xs
Example more real usage:
int div(const int x, const y)
{
check(y != 0, INT_MIN);
return x / y;
}
CodePudding user response:
Simply call return inside that function.
function YOUR_FUNCTION(){
....
....
return;
}