-3

I would like to call a function (called here just function) that accepts a variable list of arguments without knowing in advance how many arguments will be needed. I have come up with this:

int param_num
char **param // initialized and populated somewhere else
...
if (param_num == 0) result = function();
else if (param_num == 1) result = function(param[0]);
else if (param_num == 2) result = function(param[0],param[1]);
...

The above code is just a proof of concept and is not intended to be compilable. The actual function has at least one fixed argument. I cannot change the function because it belongs to an external library. The actual code is more complex and is working as expected but...

My question is: is there a more compact way of writing the same code without touching "function"?

PS working in Linux with gcc 7

PPS it is just a curiosity. There is no real problem that I am trying to solve. The above code is working as expected. Just wondering if there were a way to make it prettier.

Thanks

11
  • 1
    How about an argv style array? I.e. a null-pointer terminated array of strings (very similar to what you already have) and just pass it to the function (after modifying it to handle such an array of course). And no, there's really no way of making your code "more compact" without touching the function. Commented Dec 29, 2018 at 10:53
  • 2
    Are you sure the function is as you describe? AFAICS a variadic function must have at least one "fix" parameter. Commented Dec 29, 2018 at 11:12
  • 1
    Please avoid commenting your own question, but do take some time to edit and improve it. Consider adding some minimal reproducible example in it Commented Dec 29, 2018 at 11:16
  • 1
    In C, you cannot have the same function which is called without arguments and with several ones. This is forbidden by the language specification. Commented Dec 29, 2018 at 11:18
  • 1
    Please explain why are you asking that. Your code is invalid, and cannot even be compiled by a C compiler. I voted to close your question because it is unclear. So please improve it. Commented Dec 29, 2018 at 11:22

2 Answers 2

3

Read about <stdarg.h> and variadic functions. On Linux, see also stdarg(3). It is how you can define in C such functions of variable arity (like printf). The first few arguments should be fixed, and of known type, so you cannot have exactly what you want (with a call like function() without arguments). So a variadic function is required to have at least one first fixed-type argument (which usually determines, like in printf, the type and number of following variadic arguments). So the C language specification forbids to call the same function without any arguments and with two of them.

Be also aware of the ABI of your system. It defines calling conventions (which usually vary with the signature of the called function) For 64 bits x86 on Linux, see this (floating point and pointer arguments get passed in different registers).

GCC (specifically) has also builtins for constructing function calls, but the C11 standard n1570 don't have anything like that.

It is unclear what you exactly want to achieve, but in some cases you might generate code (e.g. pedantically use metaprogramming) at runtime. There are several ways to achieve that on Linux:

  • You could generate (in a file) some C code in /tmp/emittedcode.c, fork its compilation as a plugin (by running gcc -fPIC -shared -Wall -O -g /tmp/emittedcode.c -o /tmp/generatedplugin.so) then load that plugin using dlopen(3) (as void*dlh = dlopen("/tmp/generatedplugin.so", RTLD_NOW); but you should handle failure) and dlsym(3) of symbols there. My manydl.c example shows that you can practically do that for many hundred thousands of generated plugins.

  • You could use some JIT-compiling library like libgccjit or asmjit or libjit, or GNU lightning, etc...

In both cases, you'll then (conceptually) add a new code segment to your process and get the address of a freshly created function there into some function pointer.

Be also aware of closures and anonymous functions, and notice that C don't have them (but have to use callbacks). Read SICP.

As commented by Antti Haapala, look also into libffi (it enables you to call an arbitrary function with arbitrary arguments by "interpreting" that call, which you would describe by ad-hoc data structures).

Sign up to request clarification or add additional context in comments.

7 Comments

As I said that is not the actual code. Of course, I don't have a function without any fixed arguments at all. But thanks for your insightful answer. I will try to read those references. Anyway, it sounds more complex than I expected and maybe the solution that I used is actually the most simple and compact way to achieve what I need.
I am sorry, but your question stays very unclear and needs a lot of improvements. In particular, it lacks motivation and context. Please take a dozen of minutes to edit and improve your question (by adding several paragraphs in it).
I am thinking of a way of adding more context without going out of topic but nothing is coming to my mind. Maybe you are overthinking my question ... it is just a simple question. Is it possible to write that code in fewer lines? I was thinking about iterating over the parameter list ... but maybe I am off track.
You could iterate over the parameter list (with va_arg) but that is only possible for variadic functions which have at least one argument. Your sample code is invalid
... and with standard va_arg you need to know the type of each argument at compile time somewhere, the va_list cannot be constructed at runtime.
|
0

If you exactly know what type of args you'll need to pass, you can create a structure with possible args defined in it

you can then pass the structure and do your stuff

struct args {
    define args.... 
}
. 
. 
struct args* a;
result = function(a);

keep in mind that you'll have to add some checks in the function to see what args are passed.

1 Comment

I thought about that but I cannot modify the function. Thank you anyway for the answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.