Passing an operator as an argument to a function in C - c

I want to pass greater than (>) and less than (<) operators as arguments to a function,how is it possible..is there any way to pass those operators as arguments..please any one can help me.

You can do terrible things with macros, but in general, no, you can't do this. You typically accept a two argument function and call it, and that function can use > or < as appropriate, see the sort docs for an example.
That said, it's not super efficient (calling a function through a pointer can't be inlined, and for cheap operations like a > or < comparison, the function call overhead outweighs the comparison work). Making it efficient requires:
Multiple copies of the code, one for each possible operator (possibly generated via macros)
Moving to C++ and using templated code with functors/lambdas that can be inlined properly

There is no way to pass a 'raw' operator, but there are ways to achieve the same result.
The simplest would be a char
int func(char op, int a, int b)
{
if (op == '<')
{
return a < b;
}
else if (op == '>')
{
return a > b;
}
return -l; /* error */
}
A more complex solution would be to use a function pointer to a function that does the operation (similar to the comparator used by the sort method).

You can create a enum and pass it.
Or you can pass in a pointer to a comparison function like this:
#include <stdio.h>
int max(int a, int b, int (*comp)(int, int)) {
if (comp(a, b) < 0) {
return b;
} else {
return a;
}
}
int mycomp(int a, int b) {
return a < b ? -1 : 1;
}
int main() {
printf("%d %d\n", max(1, 2, mycomp), max(2, 1, mycomp));
}

You can write this function by using #define and #. Character #, changes an operator to a string. (for example in #define, #+ = "+").
Sample code:
#include <stdio.h>
#define great(c) ((#c==">")? (1):(0))
int main()
{
printf ("%d", great(>));
return 0;
}
In this code, I passed > as a function argument.

Related

Function pointers and callbacks in c/c++

I was trying to remind how pointers worked in c and c++ and I found this very interesting video (Pointers in C/C++). In minute 3:14:00, he begins to talk about pointer functions and callbacks, and I ended a bit confused about the real application of them.
The example case he provides consists of a sorting algorithm that takes a function pointer as argument, which defines the comparison "rule" to follow (order from geater to smaller, order from smaller to greater, from greater to smaller given the absolute values...). He eventually ends with something like this:
#include<stdio.h>
int compare(int a, int b){
if(a > b) return -1;
return 1;
}
void MyBubbleSort(int A[], int n, int (*compare)(int,int)){
int i,j,temp;
for(i=0; i<n; i++){
for(j=0; j<n-1; j++){
if(compare(A[j], A[j+1]) > 0{
temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
}
int main(){
int i, A[] = {3,2,1,5,6,4};
MyBubbleSort(A,6,compare);
for(i=0; i<6; i++) printf("%d ",A[i]);
}
When he wants to change the comparison rule, he changes the compare(int, int) content and that's all. My question is, why would he do that, instead of just having a separate function called compare(int, int) that just does the same as the one showed in the code snippet, and just call that function from within MyBubbleSort(int[], int). Wouldn't it just have the same behaviour? What are the benefits then? Are there any other interesting use cases?
Thank you very much for answers!
If I understand your question correctly, the main point is something that he mentions in the narration but does not include in the sample code: you could have several different comparison functions in your program, and use them at different times as appropriate, while still having just one MyBubbleSort function.
An example might look like:
int compare_increasing(int a, int b){
if(a > b) return -1;
return 1;
}
int compare_decreasing(int a, int b){
if(a < b) return -1;
return 1;
}
void MyBubbleSort(int A[], int n, int (*compare)(int,int));
}
int main(){
// ...
// sort in increasing order
MyBubbleSort(A,6,compare_increasing);
// sort in decreasing order
MyBubbleSort(A,6,compare_decreasing);
}
Calling a function by a pointer in this case makes the sorting function universal.
If you hardcode the comparison in that function it will work only for that condition.
C does not have lambda expressions and anonymous functions so the compare function has to be written separately and the pointer passed.

How to pass each value of an array as parameters to a function?

I have the following function that accepts a varying number of integer parameters and returns the sum.
int sum(int a, ...){
va_list nums;
va_start(nums, a);
int res=0;
for(int i=0; i<a; i++) {
res += va_arg(nums, int);
}
va_end(nums);
return res;
}
I need to pass each value of the array as a parameter to the function rather than passing the array itself. The array can be of varying length leading to a varying length of arguments to pass too.
printf("The sum is: %d", sum(size, args[0], args[1], ```need all elements of args[] array here```));
To put forth some perspective, I'm using this sum function to understand how I can go about doing this. It would be helpful to know how to achieve this in a more general setting rather than this exact function.
Please let me know if you need any more information.
Please do look at this question, which is similar, however, I require a solution in C.
The short answer is that there's no way to do exactly this in the C language. There is no ES6-like spread operator in C, nor similar functionality. I don't think there's any particular reason why they couldn't (you would just have to push more arguments onto the stack); they just never made one.
However, there are various other things you can do:
If variadic arguments were already passed into the function calling your function, you can pass along the va_list to a function declared to take a va_list. See Passing variable arguments to another function that accepts a variable argument list
As #JonathanLeffer suggests, the most natural way to write this code in C is by constructing an array of what "would be" your variadic arguments, and passing that into a function that expects an array (well, technically, a pointer, because arrays decay to pointers). For example:
int sum_array(int a, int nums[]){
int res=0;
for(int i=0; i<a; i++) {
res += nums[i];
}
return res;
}
In certain circumstances, it may be more convenient for a function like sum_array to take only the nums array/pointer, which would itself indicate the end of the array with a 0 or -1 value in the last slot. This is just another convention for indicating the end, which the caller has to set up.
You could then, if you really wanted to, write a variadic function that collects its arguments into an array and calls sum_array, if you want a variadic version as well. (Of course, you could also just implement the variadic and array versions separately, but for nontrivial functions it may be a pain to implement them twice.)
int sum_variadic(int a, ...){
va_list nums;
va_start(nums, a);
int arr[a];
for(int i=0; i<a; i++) {
arr[i] = va_arg(nums, int);
}
va_end(nums);
return sum_array(a, arr);
}
you could also use a variadic macro for the same purpose:
#define sum_macro(size, ...) sum_array(size, (int[]){__VA_ARGS__})
In summary: going from variadic to array in C is trivial, going from array to variadic is impossible.
You can also use extensions to the C language to do it anyway, as described in Passing a dynamic set of variadic arguments to a C function and In C, given a variable list of arguments, how to build a function call using them?, which #KamilCuk linked to.
You can avoid passing the number of arguments explicitly by using a variadic macro that constructs a compound literal array instead of a vararg function:
#include <stdio.h>
#define sum_int(...) (sum_int)(sizeof((int[]){__VA_ARGS__}) / sizeof(int), (int[]){__VA_ARGS__})
int (sum_int)(size_t count, const int *a) {
int sum = 0;
for (size_t i = 0; i < count; i++) {
sum += a[i];
}
return sum;
}
int main() {
printf("sum = %d\n", sum_int(1, 2, 3));
return 0;
}
This approach can be used for any purpose, as long as the types of the variable arguments are converted implicitly to the array type.
If you want to pass just the arguments to your sum function without changing its definition, you can use a variation of the macro:
#include <stdio.h>
int sum(int a, ...) {
va_list nums;
va_start(nums, a);
int res = 0;
for (int i = 0; i < a; i++) {
res += va_arg(nums, int);
}
va_end(nums);
return res;
}
#define sum(...) (sum)((int)(sizeof((int[]){__VA_ARGS__}) / sizeof(int)), __VA_ARGS__)
int main() {
printf("sum = %d\n", sum(1, 2, 3));
return 0;
}
Note however that there is no type checking with this approach and sum(1, 2.0, 3) would have undefined behavior.

What are the advantages of functions pointers over a switch case full of function calls?

Main use of function pointers (from what I gather) is to pass them along with some variables to a function which will then call the function the pointer points to. To achieve similar results one can pass an arbitrary integer instead of a function pointer and let a switch case call the appropriate function; which will also bypass the restriction that is innate to function pointers, that a function you are passing the pointer to, needs to know exactly what kind of function is coming to it (what it returns and what variables it expects.)
Is there an advantage to using function pointers over the switch case method proposed above? I'm interested in technical capabilities of function pointers that I might be missing and preferably some examples too.
If the functions each have different signatures, you'll need to have a separate case for each one in order to call the right parameters and get the right return type.
If the signatures are the same, you could instead create an array of function pointers and just index the array. This avoids branches and is simpler to maintain. For example:
int add(int, int);
int sub(int, int);
typedef int (*math_func)(int, int);
math_func arr[] = { add, sub };
int call_math_func(int idx, int a, int b)
{
return math_func[idx](a, b);
}
I prefer using function pointers when possible because imho they make intents more explicit at the calling site, e.g.:
#include <stdio.h>
typedef void (*HelloWorld)(void);
void english(void) { printf("Hello, World!\n"); }
void italian(void) { printf("Ciao, Mondo!\n"); }
void greet_world_in(HelloWorld hello_world) { hello_world(); }
int main(void)
{
greet_world_in(english);
greet_world_in(italian);
return 0;
}
Assuming that the function pointers have exactly the same kind of prototype, a switch case statement is often implemented as a jump table:
void conceptual_dispatcher_emulating_switch_case(int n) {
static const jmp_ptr_t jmp_table[5]={label_0,label_1,label_2,label_3,label_4};
if (n < 5) {
goto jmp_table[n];
}
return;
label_0 : return myfunc_1();
label_1 : return myfunc_2();
label_2 : return myfunc_3();
label_3 : return myfunc_4();
label_4 : return myfunc_5();
}
From this it's pretty easy to make an optimization:
void conceptual_dispatcher_better(int n) {
static const function_ptr_t jmp_table[5]={myfunc_1, myfunc_2, myfunc_3, myfunc_4, myfunc_5};
if (n < 5) {
goto jmp_table[n];
}
return;
}
And from this the next logical step is to
void conceptual_dispatcher_even_better(function_ptr_t *ptr) {
ptr();
}
And from this the next step is to make that inline or just call the ptr without the dispatcher.

How to make a dynamic while loop program in C?

How to make a dynamic while loop program in C?
Because of this:
if {
while
} else if {
while
} else {
while
}
I want to make a program doing dynamic while loop. I did two approaches.
first: (not work)
#include <stdio.h>
#define aaa printf("0\n")
int main() {
int x = 1, i = 1;
if (x == 1) {
#undef aaa
#define aaa printf("1\n")
} else {
#undef aaa
#define aaa printf("2\n")
}
while (i <= 10) {
aaa;
i++;
}
return 0;
}
second: (works)
#include <stdio.h>
typedef void (*FunctionName)();
void fun1();
void fun2();
int main() {
int x = 1, i = 1;
FunctionName y;
y = (x == 1) ? fun1 : fun2;
while (i <= 10) {
y();
i++;
}
return 0;
}
void fun1() {
printf("1\n");
}
void fun2() {
printf("2\n");
}
but, it can only accept same type of functions. in this case, the y().
it can't accept two or more types of functions at the same time.
for example: f1(a) and f2(a,b).
so, I have to make all functions to same type because it can't accept diff types.
this dynamic while loop program can only accept one type of functions.
then it is not full dynamic.
how can I solve the problem? how can I make it accept all kinds of functions?
any comments are welcome. thanks.
I'm not sure what problem you're trying to solve, but you could sort of make it work by sending the arguments with a void pointer.
typedef void (*FunctionName)(void *);
Then (if you want several parameters) create different structs for different functions:
struct fooArgs {
int x;
double y;
char *s;
};
Then create a function like this:
void foo(void *args) {
struct fooArgs *a = (struct fooArgs*)args;
int x = a->x;
double y = a->y;
char *s = a->s;
/* Do stuff */
}
You need to write something similar to y = (x == 1) ? fun1 : fun2; for the arguments. It could look something like this:
void *args;
struct fooArgs a = { 5, 6.7, NULL };
if(x == 1) {
y = foo;
args = a;
} else if (x == 2) {
y = bar;
args = NULL; // For a function without arguments;
}
while (i <= 10) {
y(args);
i++;
}
However, I don't recommend doing this unless you are really sure about what you are doing. If it is for performance, the gain is likely very low, and it's even likely that you just make it difficult for the compiler optimizer with worse performance as a result. Use things like this for performance as an absolute last resort, and only if you really need those extra milliseconds.
put switch or if else for more complicated conditions inside the while loop:
while(i <= 10)
{
if(condition 1)
//call f1();
...
else if (condition n)
{
// call fn;
...
else
{
// nothing of the prevous cases
}
i ++
}
you can also use swithch case inside the while loop if you are comparing against constants...
hope it helps
but, it can only accept same type of functions. in this case, the y(). it can't accept two or more types of functions at the same time. for example: f1(a) and f2(a,b). so, I have to make all functions to same type because it can't accept diff types.
Yes, because otherwise, what would be the arguments? In other words your fun1 and fun2 take no parameters. If you want to call a fun3 that takes 1 parameter, what would be the argument?
In other words, consider:
void fun3(int);
y = fun3;
y(???);
For some values of y, you would have to pass different number of arguments. Same for the return type.
What you would have to do is to create a wrapper function that does what is called a partial application of e.g. fun3:
void g() {
fun3(42);
}
y = g;
y();
Here, g has the responsibility of knowing what the arguments of fun3 are (they may be constant as in this example, or come from somewhere else).
In languages that support user-defined types (and maybe OOP), like C++, a typical solution is to create a "Callable" object that stores the arguments as data members and can be called as if it was a function.
Further, in some of those languages, you get some syntax sugar to easily create those Callable objects in-place, typically called lambdas or closures.

Enum/Dictionary-Like Tool in C?

I'm reading over a solution to a problem in K&R's chapter 7 posted here. Basically, the program will convert the standard input into lowercase or uppercase depending on the name of the program ("upper" or "lower"). It seems to store the names of the conversion functions in some kind of dictionary, like so:
int (*convcase[2])(int) = {toupper, tolower};
and later access these functions depending on whether the name of the program started with a u or an l:
if(argc > 0)
{
if(toupper((unsigned char)argv[0][0]) == 'U')
{
func = 0;
}
else
{
func = 1;
}
while((ch = getchar()) != EOF)
{
ch = (*convcase[func])((unsigned char)ch);
putchar(ch);
}
}
I understand what that code block is doing, but I've never seen anything like the initial declaration of convcase. It seems like some kind of weird combination of a macro, an enum, and an array. Could anyone explain (1) why convcase is a pointer; (2) what's with the (int) cast after its name; (3) what exactly toupper and tolower are within that declaration, because they're not char *s; and (4) when/why to use this kind of setup. Is it just a quick macro-like tool to save some space when you have multiple possible function calls?
convcase is an array of two function pointers; It's not a pointer. An array expression will be implicitly converted to a pointer when it is used in a place where a pointer is expected.
That's not a cast. It's specifying that the functions accept an int argument, as the toupper and tolower functions do.
convcase is initialised with the function pointers toupper and tolower.
I presume this question is regarding function pointers. Use function pointers when you wish for the abstraction of function pointers. I'd suggest that this example is an unnecessary use of function pointers. The ability to change convcase[0] or convcase[1] to Spanish or Japanese, depending upon user input would more likely warrant the use of function pointers in this case. Additionally, function pointers could be used in arguments to provide additional abstraction. For example, the qsort function is able to sort arrays of any type because of it's usage of function pointers for a comparer of objects. Here's an example that sorts int input using the int_compare function as the comparer.
#define nelem(array) (sizeof (array) / sizeof *(array))
int int_compare(const void *p1, const void *p2) {
int x = *(int *)p1, y = *(int *)p2;
return (x > y) - (y > x);
}
int main(void) {
int value[16];
for (size_t x = 0; x < nelem(value); x++) {
if (scanf("%d", &value[x]) != 1) {
break;
}
}
qsort(value, sizeof *value, x, int_compare);
return 0;
}

Resources