3

Say I have functions foo_1(), foo_2(),...foo_n()

How could I use a loop to call them, that is how could 'convert' a string to a function call:

for (i = 0; i < n; i++)
    switch (fork()) {
        case 0:         //child process
            *COMVAR+=m;
            //call foo_i()
            exit(4);
        case -1:
            exit(5);
   }
hierophant
  • 33
  • 4
  • 7
    You can't do that in C. You may want to consider an array of function pointers - you could then iterate over that array. – Oliver Charlesworth Oct 25 '18 at 08:56
  • 4
    Have a look at function pointers https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work?rq=1 – Mike Oct 25 '18 at 08:58
  • Can you tell us why you'd want to do that? I'm fairly certain there's no problem out there that could be solved only by defining 100 functions with arbitrary numbers in them which do exactly same thing and could be rewritten as `foo(int index)`... If you loop over it, then there should be no problems to just use `for(int i = 0; i < n; i++) { foo(i); }`, not like index in function name will be anything than just an index, otherwise you'd have named it something meaningful. The fact that nobody questions this and just answers as if it was good idea to do, is mind boggling. – Purple Ice Oct 25 '18 at 09:39
  • @PurpleIce We are learning forking currently. I was using a loop to start multiple forks and this seemed the easiest way to have each fork do a different function. – hierophant Oct 25 '18 at 10:27
  • How many times do you need to fork that you actually require a for loop? Also if each fork needs to do different thing, they maybe they are well defined enough that you can come up with names that aren't as cryptic as `foo_i` because only one forked process does foo and not all of them? By the way, if you fork in a loop, each forked process will fork again, not just the main process that started at the for loop, I don't think that's something you want anyway. I don't think you need to fork more than 5 times so I'd advise to just write them out without being lazy. – Purple Ice Oct 25 '18 at 10:33
  • So many people commenting that you “can’t” do that in C. A correct statement is that you cannot do that in a strictly conforming C program, that is, one limited to the base specification of C. But very few practical or commercial viable programs are strictly conforming C—almost all programs use additional features, such as windows. And it is common for systems to have features for looking up symbols in dynamic libraries, such as `dlsym`. So, this could be done in a non-portable way by putting the routines in a dynamic library and lookup them up at run-time. – Eric Postpischil Oct 25 '18 at 13:03
  • @PurpleIce I added the exact code I was using. The task requires me to fork a N number of times (N defined by terminal arg); – hierophant Oct 25 '18 at 15:38
  • Calling the functions isn't necessary but I was wondering if it was possible to convert a string to a function call in some way. I see that an answer below mentions that is only possible in languages with Reflection – hierophant Oct 25 '18 at 15:46
  • In that case it highly depends on what you need to do with those N processes, you should probably explain the actual problem instead of thinking about something and thinking that it's correct, ending up with xy problem. – Purple Ice Oct 25 '18 at 18:42

4 Answers4

7

You cannot have the compiler or runtime do this automatically in C, but you can manually list the function pointers and invoke them in a loop, i.e.:

// create your function prototype, which all functions must use
typedef void(*VoidFunc)(void);

// create the array of pointers to actual functions
VoidFunc functions[] = { foo_1, foo_2, foo_3 };

// iterate the array and invoke them one by one
int main(void)
{
    for (int i = 0; i < sizeof(functions) / sizeof(*functions); i++)
    {
        VoidFunc fn = functions[i];
        fn();
    }

    return 0;
}

Keep in mind that void func() is not the same as void func(void) in C.

vgru
  • 49,838
  • 16
  • 120
  • 201
5

Nope.

The best you can do involves an array of function pointers

#include <stdio.h>

typedef int (*fx)(void); // fx is pointer to function taking no parameters and returning int

int foo_1(void) { printf("%s\n", __func__); return 1; }
int foo_2(void) { printf("%s\n", __func__); return 2; }
int foo_three(void) { printf("%s\n", __func__); return 3; }

int main(void) {
    fx foo[3] = { foo_1, foo_2, foo_three };
    for (int k = 0; k < 3; k++) {
        printf("foo[%d]() returns %d\n", k, foo[k]());
    }
}

see code running on ideone

pmg
  • 106,608
  • 13
  • 126
  • 198
  • Actually, the best you can do is rewriting the function as `foo(int i)`, because if you really chose your function to have arbitrary number in it, you are clearly just working with some random hardcoded index that could be passed into the function itself... – Purple Ice Oct 25 '18 at 09:37
  • @PurpleIce: I agree the example functions I made up are not the best. Thanks for the heads up! – pmg Oct 25 '18 at 11:26
  • Oh, I'm not commenting on your answer, but the problem itself. It just doesn't really make sense to store so many functions that do exactly same thing, if they didn't, they wouldn't be called `foo_i`, the example itself is fine. Although there's better ways to solve this problem, as normally if we want to call like 5 functions and the general way of doing them is basically the same, we create yet another function which wraps those 5 functions. – Purple Ice Oct 25 '18 at 11:29
  • Not exactly what I was looking for but close enough. I didn't know about function pointers. So far the best way seems to be to use one function that takes an arg=i and using that for a switch/if statement inside the function. – hierophant Oct 25 '18 at 15:42
1

Generally , your approach isn't possible in C. But you can do it by using switch statement. Though you have to write little bit of code.

switch (n)
​{
    case 1:
        foo_1();
        break;

    case 2:
        foo_2();
        break;
    case 3:
        foo_3();
        break;
        .
        .
        .
    case n:
        foo_n();
        break;
    default:
        // code to be executed if n doesn't match any constant
}
  • 1
    Yes, I like this approach, you can also add some `bool` locks to control in timed functions` calls. – R1S8K Sep 25 '21 at 17:50
0

Higher level languages that have reflection such as Java is able to do such kind of operations, but C does not. In Java, you can do something like below:

You have a class named MyClass

public class MyClass {
    public void myMethodName(String arg1);
}

You can use below flow to call myMethodName using String form.

Class myObject = new MyClass();
Class<?> c = Class.forName("MyClass");
Class[] argTypes = new Class[] { String[].class };
Method method = c.getDeclaredMethod("myMethodName", argTypes);
method.invoke(myObject, params);

Here is the official document: https://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html

shizhen
  • 12,251
  • 9
  • 52
  • 88