Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 months ago.
Improve this question
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).
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.
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.
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;
}
Related
This questions is about my homework.
This topic is need to use like:
#define GENERIC_MAX(type)\
type type##_max(type x, type y)\
{\
return x > y ? x : y;\
}
The content of the question is to make this code run normally:
#include <stdio.h>
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
The result of the operation is like this:
i=5.2000
j=3
And this code is my current progress, but there are have problems:
#include <stdio.h>
#define printname(n) printf(#n);
#define GenerateShowValueFunc(type)\
type showValue_##type(type x)\
{\
printname(x);\
printf("=%d\n", x);\
return 0;\
}
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
I don’t know how to make the output change with the type, and I don’t know how to display the name of the variable. OAO
This original task description:
Please refer to ShowValue.c below:
#include <stdio.h>
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
Through [GenerateShowValueFunc(double)] and [GenerateShowValueFunc(int)] these two lines macro call, can help us to generated as [showValue_double( double )] and [showValue_int( int )] function, And in main() function called. The execution result of this program is as follows:
i=5.2000
j=3
Please insert the code that defines GenerateShowValueFunc macro into the appropriate place in the ShowValue.c program, so that this program can compile and run smoothly.
A quick & dirty solution would be:
type showValue_##type(type x)\
{\
const char* double_fmt = "=%f\n";\
const char* int_fmt = "=%d\n";\
printname(x);\
printf(type##_fmt, x);\
return 0;\
}
The compiler will optimize out the variable that isn't used, so it won't affect performance. But it might yield warnings "variable not used". You can add null statements like (void)double_fmt; to silence it.
Anyway, this is all very brittle and bug-prone, it was never recommended practice to write macros like these. And it is not how you do generic programming in modern C. You can teach your teacher how, by showing them the following example:
#include <stdio.h>
void double_show (double d)
{
printf("%f\n", d);
}
void int_show (int i)
{
printf("%d\n", i);
}
#define show(x) _Generic((x),\
double: double_show, \
int: int_show) (x) // the x here is the parameter passed to the function
int main()
{
double i = 5.2;
int j = 3;
show(i);
show(j);
}
This uses the modern C11/C17 standard _Generic keyword, which can check for types at compile-time. The macro picks the appropriate function to call and it is type safe. The caller doesn't need to worry which "show" function to call nor that they pass the correct type.
Without changing the shown C-code (i.e. only doing macros), which I consider a requirement, the following code has the required output:
#include <stdio.h>
#define showValue_double(input) \
showValueFunc_double(#input"=%.4f\n" , input)
#define showValue_int(input) \
showValueFunc_int(#input"=%d\n" , input)
#define GenerateShowValueFunc(type) \
void showValueFunc_##type(const char format[], type input)\
{\
printf(format, input); \
}
/* ... macro magic above; */
/* unchangeable code below ... */
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
Output:
i=5.2000
j=3
Note that I created something of a lookup-table for type-specific format specifiers. I.e. for each type to be supported you need to add a macro #define showValue_ .... This is also needed to get the name of the variable into the output.
This uses the fact that two "strings" are concatenated by C compilers, i.e. "A""B" is the same as "AB". Where "A" is the result of #input.
The rest, i.e. the required function definition is very similar to the teacher-provided example, using the ## operator.
Note, this is if the variable name has to correctly be mentioned in the output.
With out the i = things would be easier and would more elegantly use the generated functions WITHOUT having the called showValue_double(i); be explicit macros. I.e. the functions generated are 1:1 what is called from main(). I think that might be what is really asked. Let me know if you want that version.
Is there a way to "generate" a function name by using the operator ## and a variable value. For example:
#define FUN_I(fun, fun_id) fun##fun_id
#define FUN(fun, fun_id) RECV_CB_FUN_I(fun, fun_id)
int foo0(int x) {
// do something
}
int main()
{
int i = 0;
FUN(foo,i)(1);
}
Macro FUN generates fooi. Is there a way to get foo0 somehow, or I have to use the actual number 0 in this case, e.g FUN(foo, 0)(1);
Cheers
You have to use actual 0 (or another macro). Macro expansion is handled by the C pre-processor at compile time. It knows nothing about runtime values of variables.
As stated, the macro expansion is done at compile time, so the function name wouldn't be know at run time.
It is more appropriate to use function pointers and an array to them.
Example:
typedef int (*TFoo)(int);
int foo1(int x)
{
printf("from foo1: x = %d\n", x);
return 0;
}
int foo2(int x)
{
printf("from foo2: x = %d\n", x);
return 0;
}
TFoo foos[2] = {foo1, foo2};
#define foo(i, x) foos[i](x)
That's that. Hope it helps
'c' preprocessing is a process of replacing macros with the text from their definitions. some operations like ## allow to add its argument as text into definitions. So, everything is done even before compilation starts.
As a result, in your case FUN(fun,i) will be substituted as text and form funi. The only limited way to build function names like you want is to use actual text values or other macros. Here are 2 examples which will work with pre-processing:
FUN(fun, 0)(1);
or
#define I 0
FUN(fun, I)(1);
In the last case I is a macro itself, therefore it also works. (it is always a good idea to name macro name in upper case letters).
Here is an example:
#define get_i() i
int i;
int i2;
i2 = get_i();
In the case above ^^^ get_i() acts like a function that returns something(the value ofi in this case).
#define set_i(value) do{i = (value);}while(0)
set_i(i2);
This ^^^ above acts like a function that DO NOT return.
My question is, can I use macros to create a function-like macro that can both, do something, and return an object? Here is a pseudo code:
#define increse_i2_and_return_i() i2++; return i;
Is that possible?
You can use comma operator for that. The value of the last operand will be the value of an entire expression.
#define increse_i2_and_return_i() (i2++, i)
The downside of this trick is that you can't create temporary variables in a such macro.
Can the name of function and function-like macro be same?
Wouldn't this cause any problem?
They could be the same. Depending on how you use the name, either it gets replaced by preprocessor or not. For example
//silly but just for demonstration.
int addfive(int n)
{
return n + 5;
}
#define addfive(n) ((n) + 5)
int main(void)
{
int a;
a = addfive(2); //macro
a = (addfive)(2); //function
}
for ex. MS says that: http://msdn.microsoft.com/en-us/library/aa272055(v=vs.60).aspx
http://gcc.gnu.org/onlinedocs/cpp/Function-like-Macros.html#Function-like-Macros
Here you can see that calling the function, of which a macro with the same name exists, calls the macro instead :)
For the gcc at least!
This would cause no problem, but quite some confusions. I wouldn't recommend this.
I will explain via cases:
If you declared the function first then the function like macro second, macro will over take the function. i.e. it will be called always instead of the function.
//Function
double squar(double x)
{
return x*x;
}
//Macro
#define squar(x) (x*x)
On the other hand if you declare the macro first then the function later, an exception will be arise, you wont be able to build
//Macro
#define squar(x) (x*x)
//Function
double squar(double x)
{
return x*x;
}
At the end, in the first case, you still call the function like #Hayri Uğur Koltuk said here in his answer by (squar)(5)
void (assert)(int e)
{
assert(e);
}
How does it work here?
void (assert)(int e) is equivalent to void assert(int)
Why would you need it?
Consider the following example
#include<stdio.h>
void foo(int a)
{
printf("%d", a);
}
#define foo(a) {/*I do nothing*/}
int main()
{
foo(5); // won't call `foo`
}
How would you make sure when you call foo, its the function that is called and not the macro-definition substituted at the place of call?
The solution is to put an extra parenthesis like (foo)(5)
Similarly assert is already known to be a macro. That's the reason I can think of.
Since assert already is defined as a function-style macro, without the parentheses it would have been expanded both in the function header and in the body.
For example:
#define twice(x) ((x)+(x))
void twice(int i)
{
return twice(i);
}
Will expand to the following, which clearly is not legal
void ((int i)+(int i))
{
return ((i)+(i));
}
On the other hand:
#define twice(x) ((x)+(x))
void (twice)(int i)
{
return twice(i);
}
Will expand to:
void (twice)(int i)
{
return ((i)+(i));
}
The extra parentheses around the function name is simply ignored by the compiler.
This is a common trick often used in the source of the standard library, on in other contexts where there might be functions and macros with the same name.
It's legal syntax, just writing it with extra parentheses. The reason you'd do that is because assert() is often defined as a macro; so the above function exists to make assert() be a real function, probably so you can set a breakpoint in it.