I have a flat C file including ctype.h where i cant figure out how a macro works. There is this macro
#define da_dim(name, type) type *name = NULL; \
int _qy_ ## name ## _p = 0; \
int _qy_ ## name ## _max = 0
I thought it should define the type of a given value. So for example i could write
int a;
da_dim(a,"char");
to convert it to a char but it doesnt do that. I can imagine what '## name ##' is/does (like a placeholder) but i dont understand what 'qy' is and where it came from. So what is this macro for, how tu use it and (maybe) how does it work?
A macro, in C is just a simple token replacement mechanism.
Your example:
int a;
da_dim(a,"char");
Will expand to:
int a;
"char" *a = NULL;
int _qy_a_p = 0;
int _qy_a_max = 0;
So, if will expand to errors because you will have two a identifiers and "char" is not expected where you are placing it.
If you are using gcc, you can "see" macro expansions by doing:
$ gcc -E your_program.c
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.
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
This question already has answers here:
What are the applications of the ## preprocessor operator and gotchas to consider?
(13 answers)
Closed 6 years ago.
I am having a code that says:
#include<stdio.h>
typedef struct string{
char *ch_ptr;
}str_t;
#define newdef(a,b) \
char a ## sumthing[b * sizeof(str_t)]; \
str_t *a = (str_t *)a ## sumthing
main(){
newdef(input,5);
/* some lines of code */
}
Optional changes to code:
#include<stdio.h>
typedef struct string{
char *ch_ptr;
}str_t;
#define newdef(a,b) \
char a ## sumthing[b * sizeof(str_t)]; \
str_t *var1 = (str_t *)a ## sumthing
main(){
newdef(input,5)="Hello";
printf("%s\n",input);
/* some lines of code */
}
Can anyone explain what this code segment means? Is input in this code a string (hope not) or a variable? If a variable then why doesn't the compiler throw an undeclared variable error?
Its a preprocessor concatenation operator, and can only be used when defining preprocessor macros.
Lets take a simple example
#define CONCAT(a, b) a ## b
int CONCAT(foo, bar);
In the above code, the invocation of CONCAT(foo, bar) will be replaced by
int foobar;
input is neither a string nor a variable, it's a preprocessing token.
## is the "token-pasting" operator.
The first macro expands newdef(input,5); into
char inputsumthing[5 * sizeof(str_t)]; str_t *input = (str_t *) intputsumthing;
That is, it expands into a declaration of a variable named like the first parameter.
Your "optional changes" would unconditionally name the declared pointer variable "var1" and make it impossible to use the macro more than once in the same scope.
Also, newdef(input,5)="Hello"; would expand to an error:
char inputsumthing[5 * sizeof(str_t)];
str_t *var1 = (str_t *)inputsumthing = "Hello";
As a side note, the original macro seems to mostly be an obfuscation of
str_t inputs[5];
str_t* input = inputs;
I am trying to write a macro which returns the smallest value of several integers. When I compile the following code, it throws an error "expected expression". I don't know what's wrong there. Could anyone point out the issues with this code?
#define SMALLEST (nums, (ret_val), ...) \
do { \
int i, val; \
va_list vl; \
va_start(vl,nums); \
(*ret_val) = va_arg(vl, int); \
for (i = 1; i < nums; i++) \
{ \
val=va_arg(vl, int); \
if ((*ret_val) > val) \
(*ret_val) = val; \
} \
va_end(vl); \
} while(0)
int main ()
{
int nums = 3;
int ret_val = 0;
SMALLEST(nums, &ret_val, 1, 2, 3);
return 0;
}
I am just curious about how to do it with Macro.
I am just curious about how to do it with Macro.
You can't. va_list is a way for a variadic function to access its arguments. What you have written is a variadic macro. They are not the same (in particular the variadic macro is still only a syntactic convenience that does not let you process individual arguments). The only way to do what you want is to call a variadic function of your own design inside the variadic macro (and then you might as well eliminate the macro).
However, if you really insist on using a variadic macro, it turns out that you are lucky that the same separator , is used in macro arguments and in array initializers, so you can try something like:
#define F(X, ...) \
do { \
int t[] = { __VA_ARGS__ }; \
for (int i = 0; i < sizeof t / sizeof t[0]; i++) \
… \
} while (0)
I don't think you can. From the gcc manual (https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html) the best you can do in a standard way is write __VA_ARGS__, which will expand the arguments in place (for example to pass to a function).
It then goes on to define other non-standard extensions, which you might be able to use, but wouldn't be standard.
Why not do it with a function?
The way you deal with argument lists in variadic macros is not the same as the way you deal with them in variadic functions. Instead of using va_list and its related macros, you use __VA_ARGS__.
That is pretty much the extent of it: you cannot write a macro that processes variadic list from the beginning to the end; you are limited to passing the arguments through to a variadic function, which performs the actual processing.
Note: Your implementation is incorrect, too: you should be using va_start(vl,ret_val) instead of va_start(vl,nums), because you are supposed to pass the last argument before ... to va_start.
If I were to rewrite this as a function, though, I would drop the ret_val pointer, and make a function that returns a value the regular way.
It makes no sense to do that with macro. That's what functions are for.
You get an error because the SMALLEST symbol in your main function gets replaced by the whole body of the function you've defined. AFAIK you can't define a function inside another function in C.
Is there any particular reason why you want to use a macro here? You seem to be confusing macro syntax and standard syntax (the reason for your error).
You should use a function to achieve this - this is what a function is for. The following code should get you what you want:
int Smallest( int iNumberOfIntegers, ... )
{
va_list args = NULL;
int i = 0;
int iSmallestValue = 0;
int iCurrentValue = 0;
va_start( args, iNumberOfIntegers );
iSmallestValue = va_arg( args, int );
for(i = 0; i < iNumberOfIntegers - 1; i++)
{
iCurrentValue = va_arg( args, int );
if(iSmallestValue > iCurrentValue)
{
iSmallestValue = iCurrentValue;
}
}
return iSmallestValue;
}
Of note, you you need to pass the size of the variadic argument if you are going to loop over it in this manner. This is not necessary in format strings because the compiler can infer the number from the format string specifiers.
We subtract 1 from the loop to account for a 0 offset.
Edit: And, as others have said, you can't use a variadic macro in the way you were trying.
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.