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.
Related
I'm trying to make some functions, taking unknown type parameters, to generically apply functions.
Let's take for example a function that could apply close(int fd) for each element of an array:
void for_each(void *array[], void (*func)(void *))
{
for (size_t i = 0; array[i] != NULL; ++i)
func(array[i]);
}
If I want to use this function with close(int fd), I have to make a wrapping function like this:
void close_fd(void *fd)
{
close(*(int *)fd);
}
I would like to use this for_each function with strings, floats and everything else.
Isn't there something that could achieve it, without the wrapping part ?
I know that C++ have a lot of way to do it, lambdas, templates etc., but is there a good way in C ? A compromise ?
Well, it is clear that you want to call several times a function (the same function) for different data. But those data are passed in an array, with by definition is a storage of several data items of the same type. So finally there's no special construct to do that, just do it in plain C:
typedef .... MY_TYPE;
/* define a pointer to represent the type of callback pointer you are using */
typedef void (*callback_ptr)(MY_TYPE param);
/* this is the real callback function you are going to use */
void my_func1(MY_TYPE param){
/* process a single MY_TYPE */
}
void my_funcN(MY_TYPE param) {
/* another process function */
}
/* function to apply the callback to an array of MY_TYPE */
void for_each( MY_TYPE array[], size_t array_sz, callback_ptr f )
{
int i;
for (i = 0; i < array_sz; i++)
f(array[i]);
}
....
MY_TYPE my_array[100] = { ... };
size_t my_array_sz = sizeof my_array / sizeof my_array[0];
for_each(my_array, my_array_sz, my_func1); /* process all by my_func1 */
for_each(my_array, my_array_sz, my_funcN); /* process all by my_funcN */
Try to avoid using void * when it's not strictly necessary. Probably in an early design phase, you don't know the actual type of data it is going to process, but it's clear that once you write the actual call statement, you have to put parameters and use the return value, so you are sticking then to actual types.... and that gives you the needed hint on how you have to declare the callback pointer, and the process functions. Putting the actual types in the function call makes the compiler to check for correctness, and that's a help for you to avoid commiting mistakes.
generic functions
Generic functions are not supported in C, but if you want some kind of arrangement, that allows you to write functions in which some data type is generic, you can simulate that with macros (you have to write very carefully the macros to work, but very good approximations can be achieved)
You can define a different function for each type, with a cpp macro, as in:
func_def.h
#define FUNC(TYPE) \
void my_func_##TYPE( TYPE param ) \
{ \
/* body of function */ \
}
and then include in file scope, the following functions:
program.c
FUNC(int)
FUNC(double)
and that will expand into:
void my_func_int( int param ) \
{ \
/* body of function */ \
}
void my_func_double( double param ) \
{ \
/* body of function */ \
}
And you'll get type checking in parameters anyway. As you see, you have to use the type in the function name, as C doesn't support overloading of functions (functions with same name and different argument lists) In this case, both, the my_func_* callbacks, and the for_each_* functions will have to be defined, as for the compiler to fully do type checking.
As mentioned in the comments, you can achieve this with a macro. Also it's more idiomatic in C to pass the size of an array into the function that uses it, rather than rely on sentinel values (strings being the exception).
#define for_each(array, array_size, func) do { \
for (size_t i = 0; i < (array_size); ++i) { \
func((array)[i]); \
} \
} while(0)
Usage:
#define ARRAY_SIZE(array) (sizeof((array)) / sizeof(*(array)))
void int_func(int arg)
{
}
void string_func(const char *arg)
{
}
int int_array[5];
const char *string_array[5];
void calling_func(void)
{
for_each(int_array, ARRAY_SIZE(int_array), string_func); // Warning: pointer from integer without a cast
for_each(string_array, ARRAY_SIZE(string_array), int_func); // Warning: integer from pointer without a cast
}
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.
Currently, I have a very simple function to deallocate array of doubles in my program:
void deallocate(double** array)
{
free(*array);
}
I would like this function to be variadic in order to take several arrays, and free them one after another. I've never written a variadic function, and as there may exist tricks with pointers I would like to know how to do that.
Don't do this with a variadic function, this concept should be retired. In particular it makes no sense at all for something that is to receive arguments of all the same type, void*.
Just have a simple function, first that receives an array of pointers
void free_arrays(void* a[]) {
for (size_t i = 0; a[i]; ++i) free(a[i]);
}
Then you can wrap that with a macro like that
#define FREE_ARRAYS(...) free_arrays((void*[]){ __VA_ARGS__, 0 })
This supposes that none of your pointers is already 0, since the processing would stop at that point.
If you'd have a need to have that working even if some of the pointers are 0, you'd have to pass the number of elements as a first parameter to your function. This is a bit tedious but can be determined in the macro, too.
void free_arrays0(size_t n, void* a[]) {
for (size_t i = 0; i < n; ++i) free(a[i]);
}
#define FREE_ARRAYS0(...) \
free_arrays( \
sizeof((void*[]){ __VA_ARGS__})/sizeof(void*), \
(void*[]){ __VA_ARGS__} \
)
You can do it like this:
void deallocate(double *p, ...)
{
va_list ap;
va_start(ap, p);
do {
free(p);
p = va_arg(ap, double *);
} while (p);
va_end(ap);
}
Call as deallocate(p1, p2, p3, (double *)NULL). You need the NULL (or some other value) as a sentinel to signal the end of the argument list; none of the other pointers should be NULL or the loop will stop prematurely.
I'm not saying that this is a good idea, though: varargs functions have their use cases, but they're error-prone with pointers because some implicit conversions don't take place (because the compiler doesn't know the type of the arguments beyond the first).
I just came to C from C# and was looking for a way to define generic functions like those in C#. I came across this post but when I tried to compile it I get a bunch of errors ("`n' undeclared here (not in a function)", " syntax error before "array" ", etc.)
Here's my code:
#include<conio.h>
#include<stdlib.h>
#define MAKE_PRINTEACH(TYPE)\
void printeach_##TYPE (TYPE[n] array, int n, void(*f)(TYPE)){\
int i;\
for(i = 0; i < n; i++) {\
f(array[i]);\
}\
}
MAKE_PRINTEACH(int)
MAKE_PRINTEACH(float)
void printInt(int x)
{
printf("got %d\n",x);
}
void printFloat(float x)
{
printf("got %f\n",x);
}
int main()
{
int[5] ia = {34,61,3,6,76};
float[6] fa = {2.4,0.5,55.2,22.0,6.76,3.14159265};
printeach_int(ia, 5, printInt);
printeach_float(fa,6,printFloat);
getch();
}
What am I doing wrong here?
I am using DevC++ if that makes a difference.
A correct version would look like this
#define MAKE_PRINTEACH(TYPE) \
void printeach_##TYPE (size_t n, TYPE array[n], void(*f)(TYPE)){ \
for(size_t i = 0; i < n; i++) { \
f(array[i]); \
} \
}
to summarize what went wrong with your version:
n must be declared before it is used
the array bounds come after the identifier
the semantically correct type for array sizes and things like that is size_t
C since C99 also has local variables for for loops.
You might try this variation:
#define MAKE_PRINTEACH(TYPE)\
void printeach_##TYPE (TYPE * array, int n, void(*f)(TYPE)){\
int i;\
for(i = 0; i < n; i++) {\
f(array[i]);\
}\
}
The TYPE[n] array implies the compiler supports VLA (Variable Length Array) and I do not know whether your compiler does.
For gcc adding the command line option -std=c99 would make the original code compile.
Update:
Corrections applied as by Jens's comment.
The solution I propose is to simply pass a pointer to a variable of the type which the array (as proposed in the OP) would have contained. Doing so, is the way arrays are passed to a function. They are passed by reference.
Also Jens mentions several other warnings/errors. As there are:
1 conio.h is not a standard C include, stdio.h whould be appropriate here
2 Arrays are declared by adding the array's size to the variable name, not to the type. It has to be: int ia[5]not int[5] ia
3 main() returns int, the OP does not return anything.
4 The prototype for getch() is missing. One might like to include curses.h
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.