Can a C macro contain temporary variables? - c

I have a function that I need to macro'ize. The function contains temp variables and I can't remember if there are any rules about use of temporary variables in macro substitutions.
long fooAlloc(struct foo *f, long size)
{
long i1, i2;
double *data[7];
/* do something */
return 42;
}
MACRO Form:
#define ALLOC_FOO(f, size) \
{\
long i1, i2;\
double *data[7];\
\
/* do something */ \
}
Is this ok? (i.e. no nasty side effect - other than the usual ones : not "type safe" etc). BTW, I know "macros are evil" - I simply have to use it in this case - not much choice.

There are only two conditions under which it works in any "reasonable" way.
The macro doesn't have a return statement. You can use the do while trick.
#define macro(x) do { int y = x; func(&y); } while (0)
You only target GCC.
#define min(x,y) ({ int _x = (x), _y = (y); _x < _y ? _x : _y; })
It would help if you explain why you have to use a macro (does your office have "macro mondays" or something?). Otherwise we can't really help.

C macros are only (relatively simple) textual substitutions.
So the question you are maybe asking is: can I create blocks (also called compound statements) in a function like in the example below?
void foo(void)
{
int a = 42;
{
int b = 42;
{
int c = 42;
}
}
}
and the answer is yes.
Now as #DietrichEpp mentioned it in his answer, if the macro is a compound statement like in your example, it is a good practice to enclose the macro statements with do { ... } while (0) rather than just { ... }. The link below explains what situation the do { ... } while (0) in a macro tries to prevent:
http://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html
Also when you write a function-like macro always ask yourself if you have a real advantage of doing so because most often writing a function instead is better.

First, I strongly recommend inline functions. There are very few things macros can do and they can't, and they're much more likely to do what you expect.
One pitfall of macros, which I didn't see in other answers, is shadowing of variable names.
Suppose you defined:
#define A(x) { int temp = x*2; printf("%d\n", temp); }
And someone used it this way:
int temp = 3;
A(temp);
After preprocessing, the code is:
int temp = 3;
{ int temp = temp*2; printf("%d\n", temp); }
This doesn't work, because the internal temp shadows the external.
The common solution is to call the variable __temp, assuming nobody will define a variable using this name (which is a strange assumption, given that you just did it).

This is mostly OK, except that macros are usually enclosed with do { ... } while(0) (take a look at this question for explanations):
#define ALLOC_FOO(f, size) \
do { \
long i1, i2;\
double *data[7];\
/* do something */ \
} while(0)
Also, as far as your original fooAlloc function returns long you have to change your macro to store the result somehow else. Or, if you use GCC, you can try compound statement extension:
#define ALLOC_FOO(f, size) \
({ \
long i1, i2;\
double *data[7];\
/* do something */ \
result; \
})
Finally you should care of possible side effects of expanding macro argument. The usual pattern is defining a temporary variable for each argument inside a block and using them instead:
#define ALLOC_FOO(f, size) \
({ \
typeof(f) _f = (f);\
typeof(size) _size = (size);\
long i1, i2;\
double *data[7];\
/* do something */ \
result; \
})

Eldar's answer shows you most of the pitfalls of macro programming and some useful (but non standard) gcc extension.
If you want to stick to the standard, a combination of macros (for genericity) and inline functions (for the local variables) can be useful.
inline
long fooAlloc(void *f, size_t size)
{
size_t i1, i2;
double *data[7];
/* do something */
return 42;
}
#define ALLOC_FOO(T) fooAlloc(malloc(sizeof(T)), sizeof(T))
In such a case using sizeof only evaluates the expression for the type at compile time and not for its value, so this wouldn't evaluate F twice.
BTW, "sizes" should usually be typed with size_t and not with long or similar.
Edit: As to Jonathan's question about inline functions, I've written up something about the inline model of C99, here.

Yes it should work as you use a block structure and the temp variables are declared in the inner scope of this block.
Note the last \ after the } is redundant.

A not perfect solution: (does not work with recursive macros, for example multiple loops inside each other)
#define JOIN_(X,Y) X##Y
#define JOIN(X,Y) JOIN_(X,Y)
#define TMP JOIN(tmp,__LINE__)
#define switch(x,y) int TMP = x; x=y;y=TMP
int main(){
int x = 5,y=6;
switch(x,y);
switch(x,y);
}
will become after running the preprocessor:
int main(){
int x=5,y=6;
int tmp9 = x; x=y; y=tmp9;
int tmp10 = x; x=y; y=tmp10;
}

They can. They often shouldn't.
Why does this function need to be a macro? Could you inline it instead?

If you're using c++ use inline, or use -o3 with gcc it will inline all functions for you.
I still don't understand why you need to macroize this function.

Related

A homework is about use macro

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.

Prepocessor ## Operator and variable

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).

declaring variable length array as macro

Can on do this:
#define VARIABLE_LENGTH_CHAR_ARRAY(name, size) \
int temp_array_size_macro_index = size; \
char "#name"[temp_array_size_macro_index];
and in the main use it like:
main(){
VARIABLE_LENGTH_CHAR_ARRAY(local_char_array, 16);
}
would this go against the coding styles or would it be plagued with macro issues?
I know you need to be careful with the variable name!
if I am right you want something like that :
#define VARIABLE_LENGTH_CHAR_ARRAY(name, size) \
const int size_of_##name = size; \
char name[size_of_##name]
int main()
{
VARIABLE_LENGTH_CHAR_ARRAY(local_char_array, 16);
}
The name of the (now const) variable for the size now depends on the name of the array itself, that minimize the probability to have homonyms
The expansion of that code produced by gcc -E gives :
int main()
{
const int size_of_local_char_array = 16; char local_char_array[size_of_local_char_array];
}
But to do that it is strange :
as __J__ I think this not helps to make the program readable
else where in your source size_of_local_char_array can be used but if you/someone search for its definition it will not be found
the macro produces two statements, and of course in that case it is not possible to group them in a block {}, this is dangerous because this is not intuitive. As you can see in your code you added a useless ';' after the use of the macro while a final ';' is already present in the macro definition

Use of pasting operator `##` with types in C

Is it possible to define a macro for the C preprocessor which takes an array as argument and expands to <type of array elements>_string? For example if x in an array of integers the macro invoked with argument x should expand to int_string.
I tried with
#define TypePaste(array) typeof(array[0])##_string
but it expands to )_string.
Even using multiple levels of indirection for the ## operand the macro doesn't expand correctly.
That's not possible. At the translation phase (the preprocessing phase) where macros are expanded and tokens are concatenated, the compiler (at this point, the preprocessor) does not yet have the notion of a type and thus cannot possibly generate types.
It is not all that clear what problem you are trying to solve, but given your comment:
the macro should expand to the name of an existing function. I'd like to define a function <type>_string for every existing type and then use the macro to select the right function according to the type of the array given.
Then you could use the C11 _Generic keyword:
#include <stdio.h>
void int_string (size_t size, int array[size])
{
printf("I am %s, do stuff here.\n", __func__);
}
void float_string (size_t size, float array[size])
{
printf("I am %s, do stuff here.\n", __func__);
}
#define TypePaste(array) \
_Generic( array, \
int: int_string, \
float: float_string ) \
(sizeof(array)/sizeof(*array), array) // function parameters
int main()
{
int i_arr[5];
float f_arr[3];
TypePaste(i_arr);
TypePaste(f_arr);
}
Output:
I am int_string, do stuff here.
I am float_string, do stuff here.
Note: this assumes that the passed parameter is a local/file scope allocated array. If passing a pointer, there's no type safety and the program will fail.
C11's _Generic type selection is the "proper" way to do what you want. There are other, platform dependent solutions, tough.
If you are using gcc – you don't say so eplicitly, but you use gcc's extension typeof already – you can use gcc's statement expresions and nested functions to create a comparison function for qsort on the spot:
double a[5] = {8.4, 8.1, 9.3, 12.2, 5.2};
qsort(a, 5, sizeof(*a), ({
int cmp(const void *p, const void *q) {
const typeof(a[0]) *pp = p;
const typeof(a[0]) *qq = q;
return (*pp < *qq) ? -1 : (*pp > *qq);
}
cmp;
}));
This creates a function and returns its address. (The last statement of a compound expression is its value. The scope of the local variables is the statement expression, but a nested function is not created on the stack so its safe to return a pointer to that function.)
For primitive types, where you want to sort according to the comparison operators < and >, you can turn that into a macro:
#define COMPARE(ARRAY)({ \
int cmp(const void *p, const void *q) { \
const typeof(ARRAY[0]) *pp = p; \
const typeof(ARRAY[0]) *qq = q; \
return (*pp < *qq) ? -1 : (*pp > *qq); \
} \
cmp; \
})
qsort(a, 5, sizeof(*a), COMPARE(a));
or even:
#define SORT(ARRAY, N) \
qsort(ARRAY, N, sizeof(*ARRAY), COMPARE(ARRAY))
SORT(a, 5);
That's not Standard C, so if you need compatibility between platforms, this is out of the question.

Typechecking macro arguments in C

Is it possible to typecheck arguments to a #define macro? For example:
typedef enum
{
REG16_A,
REG16_B,
REG16_C
}REG16;
#define read_16(reg16) read_register_16u(reg16); \
assert(typeof(reg16)==typeof(REG16));
The above code doesn't seem to work. What am I doing wrong?
BTW, I am using gcc, and I can guarantee that I will always be using gcc in this project. The code does not need to be portable.
gcc supports typeof
e.g. a typesafe min macro taken from the linux kernel
#define min(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; })
but it doesn't allow you to compare two types. Note though the pointer comparison which Will generate a warning - you can do a typecheck like this (also from the linux kernel)
#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})
Presumably you could do something similar - i.e. compare pointers to the arguments.
The typechecking in C is a bit loose for integer-related types; but you can trick the compiler by using the fact that most pointer types are incompatible.
So
#define CHECK_TYPE(var,type) { __typeof(var) *__tmp; __tmp = (type *)NULL; }
This will give a warning, "assignment from incompatible pointer type" if the types aren't the same. For example
typedef enum { A1,B1,C1 } my_enum_t;
int main (int argc, char *argv) {
my_enum_t x;
int y;
CHECK_TYPE(x,my_enum_t); // passes silently
CHECK_TYPE(y,my_enum_t); // assignment from incompatible pointer type
}
I'm sure that there's some way to get a compiler error for this.
This is an old question, But I believe I have a general answer that according to Compiler Explorer apears to work on MSVC, gcc and clang.
#define CHECK_TYPE(type,var) { typedef void (*type_t)(type); type_t tmp = (type_t)0; if(0) tmp(var);}
In each case the compiler generates a useful error message if the type is incompatible. This is because it imposes the same type checking rules used for function parameters.
It can even be used multiple times within the same scope without issue. This part surprises me somewhat. (I thought I would have to utilize "__LINE__" to get this behavior)
Below is the complete test I ran, commented out lines all generate errors.
#include <stdio.h>
#define CHECK_TYPE(type,var) { typedef void (*type_t)(type); type_t tmp = (type_t)0; if(0) tmp(var);}
typedef struct test_struct
{
char data;
} test_t;
typedef struct test2_struct
{
char data;
} test2_t;
typedef enum states
{
STATE0,
STATE1
} states_t;
int main(int argc, char ** argv)
{
test_t * var = NULL;
int i;
states_t s;
float f;
CHECK_TYPE(void *, var); //will pass for any pointer type
CHECK_TYPE(test_t *, var);
//CHECK_TYPE(int, var);
//CHECK_TYPE(int *, var);
//CHECK_TYPE(test2_t, var);
//CHECK_TYPE(test2_t *, var);
//CHECK_TYPE(states_t, var);
CHECK_TYPE(int, i);
//CHECK_TYPE(void *, i);
CHECK_TYPE(int, s); //int can be implicitly used instead of enum
//CHECK_TYPE(void *, s);
CHECK_TYPE(float, s); //MSVC warning only, gcc and clang allow promotion
//CHECK_TYPE(float *, s);
CHECK_TYPE(float, f);
//CHECK_TYPE(states_t, f);
printf("hello world\r\n");
}
In each case the compiler with -O1 and above did remove all traces of the macro in the resulting code.
With -O0 MSVC left the call to the function at zero in place, but it was rapped in an unconditional jump which means this shouldn't be a concern. gcc and clang with -O0 both remove everything except for the stack initialization of the tmp variable to zero.
No, macros can't provide you any typechecking. But, after all, why macro? You can write a static inline function which (probably) will be inlined by the compiler - and here you will have type checking.
static inline void read_16(REG16 reg16) {
read_register_16u(reg16);
}
Building upon Zachary Vander Klippe's answer, we might even go a step further (in a portable way, even though that wasn't a requirement) and additionally make sure that the size of the passed-in type matches the size of the passed-in variable using the "negative array length" trick that was commonly used for implementing static assertions in C (prior to C11, of course, which does provide the new _Static_assert keyword).
As an added benefit, let's throw in some const compatibility.
#define CHECK_TYPE(type,var) \
do {\
typedef void (*type_t) (const type);\
type_t tmp = (type_t)(NULL);\
typedef char sizes[((sizeof (type) == sizeof (var)) * 2) - 1];\
if (0) {\
const sizes tmp2;\
(void) tmp2;\
tmp (var);\
}\
} while (0)
Referencing the new typedef as a variable named tmp2 (and, additionally, referencing this variable, too) is just a method to make sure that we don't generate more warnings than necessary, c.f., -Wunused-local-typedefs and the like. We could have used __attribute__ ((unused)) instead, but that is non-portable.
This will work around the integer promotion "issue" in the original example.
Example in the same spirit, failing statements are commented out:
#include <stdio.h>
#include <stdlib.h>
#define CHECK_TYPE(type,var) \
do {\
typedef void (*type_t) (const type);\
type_t tmp = (type_t)(NULL);\
typedef char sizes[((sizeof (type) == sizeof (var)) * 2) - 1];\
if (0) {\
const sizes tmp2;\
(void) tmp2;\
tmp (var);\
}\
} while (0)
int main (int argc, char **argv) {
long long int ll;
char c;
//CHECK_TYPE(char, ll);
//CHECK_TYPE(long long int, c);
printf("hello world\n");
return EXIT_SUCCESS);
}
Naturally, even that approach isn't able to catch all issues. For instance, checking signedness is difficult and often relies on tricks assuming that a specific complement variant (e.g., two's complement) is being used, so cannot be done generically. Even less so if the type can be a structure.
To continue the idea of ulidtko, take an inline function and have it return something:
inline
bool isREG16(REG16 x) {
return true;
}
With such as thing you can do compile time assertions:
typedef char testit[sizeof(isREG16(yourVariable))];
No. Macros in C are inherently type-unsafe and trying to check for types in C is fraught with problems.
First, macros are expanded by textual substitution in a phase of compilation where no type information is available. For that reason, it is utterly impossible for the compiler to check the type of the arguments when it does macro expansion.
Secondly, when you try to perform the check in the expanded code, like the assert in the question, your check is deferred to runtime and will also trigger on seemingly harmless constructs like
a = read_16(REG16_A);
because the enumerators (REG16_A, REG16_B and REG16_C) are of type int and not of type REG16.
If you want type safety, your best bet is to use a function. If your compiler supports it, you can declare the function inline, so the compiler knows you want to avoid the function-call overhead wherever possible.

Resources