I was wondering whether there is anything wrong with passing a pointer to putchar, or any other standard function which can be implemented as a macro, to a function accepting a function pointer. Below is an example of what I'm doing.
#include <stdio.h>
static int print(const char *s, int (*printc)(int))
{
int c;
while (*s != '\0') {
if ((c = printc(*s++)) < 0)
return c;
}
return printc('\n');
}
int main(void)
{
print("Hello, world", putchar);
return 0;
}
I don't have any problems compiling this with GCC and Clang under GNU/Linux, as well as GCC under OpenBSD. I'm wondering whether it will have the same behaviour under every other standard compliant implementation, since putchar can be implemented as a macro. I've searched through the standard, particularly the sections on function pointers and putchar, and haven't been able to find anything that specifies whether this is legal or not.
Thanks.
Following on from my comments-based discussion with #pmg, I found the relevant section of the standard (C99, 7.1.4 p.1):
... it is permitted to take the address of a library function even if it is also defined as
a macro.161)
161) This means that an implementation shall provide an actual function for each library function, even if it also provides a macro for that function.
It is legal, because it refers to the library function, not the macro. When it is defined as a macro, that macro takes an argument, and therefore putchar with no parenthesis following does not refer to it.
This is an instance of using a macro to inline functions, and should not be taken as good practice now that inlining is supported by compilers.
The macro is only "invoked" when its identifier is followed by an open-parenthesis (. Otherwise the real function of the same name is invoked/used.
#include <stdio.h>
#define macro(x) 42
int (macro)(int x) { return x; }
int main(void) {
printf("%d %d\n", macro(1), (macro)(1));
}
The function definition has "extra" parenthesis to prevent the macro from being expanded
See code running at ideone: http://ideone.com/UXvjX
Related
I am starting to learn programming in C language the book I am refering to code shows some source code with gets() and my IDLE recognises it as well. But still while compiling it, my compiler doesn't agree with it.
Can anyone help me out? I am using gets() in the main function and using clang as the compiler.
Expanding on my comment:
First, never use gets(), for any reason, even in toy code. If you see it in an example program, ignore the example and move on. It was deprecated in C99 and removed from the standard library completely in C2011 because it was a major security hole. The heartburn caused by that one function was worth breaking 30-some-odd years of legacy code.
Second, under C89 and earlier, if the compiler saw a function call before it saw a declaration or definition, it would assume the function returned int - IOW, the function had an implicit declaration of int. If you had a function definition later in the same translation unit, and the function returned an int, you were fine:
int foo( void )
{
int x = bar(); // bar *implicitly* declared to return int
}
int bar( void ) // implicit declaration matches definition, we're good
{
return some_integer_value;
}
However, if bar did not return an int, you'd get an error because the implicit int declaration did not match up with the non-int definition.
gets() returns char *, not int, so an implicit declaration of gets is incorrect regardless.
C99 removed implicit int declarations entirely - since then, all functions must be declared or defined before they are called.
EDIT
The most likely reason you're getting that implicit declaration error is that your compiler is recent enough that it no longer has a declaration for gets in stdio.h.
You're getting a message like "implicit declaration of gets is not allowed" for the same reason you'd get the message "implicit declaration of my_undeclared_function is not allowed" if you tried to call my_undeclared_function. These days, gets is not a standard C library function.
To explain in more detail: in modern C, if you write
int main()
{
f();
}
int f()
{
return 0;
}
you will typically get a message like "implicit declaration of function 'f' is invalid in C99". Once upon a time, if you called a function the compiler hadn't heard of (yet), it assumed it was going to be a function returning int, but that assumption was removed in C99.
On the other hand, if you write
#include <stdio.h>
int main()
{
char line[100];
printf("type something:\n");
fgets(line, sizeof(line), stdin);
printf("you typed: %s", line);
return 0;
}
you will not get that message about the functions printf and fgets. These are functions that the compiler has heard of: their declarations are in <stdio.h>.
But if you write
#include <stdio.h>
int main()
{
char line[100];
printf("type something:\n");
gets(line);
printf("you typed: %s", line);
return 0;
}
you will get the message again, about function gets(), because gets is not a function the compiler has heard of. It is not a standard function; it is not declared in <stdio.h>.
Now, once upon a time, gets was a standard function and it was declared in <stdio.h>, but it was a spectacularly ill-conceived and dangerous function, so it has been removed from the standard. The book you read recommending it is quite out-of-date.
You didn't #include <stdio.h>, simple as that.
In C99, you get the error if you use this exact code:
int main (void)
{
char buf[10];
gets(buf);
return 0;
}
Including stdio.h fixes the problem. Though notably, gets was flagged as an obsolete function in C99 and removed entirely from the language in C11. So the following code will not compile in standard C (C11):
#include <stdio.h>
int main (void)
{
char buf[10];
gets(buf);
return 0;
}
So possibly you could get the error because you compile as standard C instead of C99.
(Note that the Windows Mingw compiler specifically might use a C11 compiler but a C99 standard lib, so you may get some odd outcomes with that one.)
See Why is the gets function so dangerous that it should not be used? for details.
I'm relatively new to C. I've come across a form of function syntax I've never seen before, where the parameter types are defined after that parameter list. Can someone explain to me how it is different than the typical C function syntax?
Example:
int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
That's the old-style syntax for parameter lists, which is still supported. In K&R C you could also leave off the type declarations and they would default to int. i.e.
main(argc, argv)
char *argv[];
{
return 0;
}
would be the same function.
What's also interesting is the calling convention difference of functions with, and functions without a prototype. Consider an old style definition:
void f(a)
float a; {
/* ... */
}
In this case, the calling convention is that all arguments are promoted before being passed to the function (for example, a float argument is first promoted to double, before being passed). So if f receives a double but the parameter has type float (which is perfectly valid) the compiler has to emit code that converts the double to a float prior to executing the function's body.
If you include a prototype, the compiler does not do such automatic promotions anymore and any data passed is converted to the types of the parameters of the prototype as if by assignment. So the following is not legal and results in undefined behavior:
void f(float a);
void f(a)
float a; {
}
In this case, the function's definition would convert the submitted parameter from double (the promoted form) to float because the definition is old-style. But the parameter was submitted as a float, because the function has a prototype. For example, clang gives
main.c:3:9: warning: promoted type 'double' of K&R function parameter is not compatible with the parameter type 'float' declared in a previous prototype [-Wknr-promoted-parameter]
Your options of solving the contradictions are the two following:
// option 1
void f(double a);
void f(a)
float a; {
}
// option 2
// this declaration can be put in a header, but is redundant in this case,
// since the definition exposes a prototype already if both appear in a
// translation unit prior to the call.
void f(float a);
void f(float a) {
}
Option 2 should be preferred if you have the choice because it gets rid of the old style definition up front. If such contradicting function types for a function appears in the same translation unit, the compiler will usually tell you (but is not required). If such contradictions appear over multiple translation units, the error will possibly go unnoticed and can result in hard to predict bugs. It is best to avoid these old style definitions.
This is the so caller K&R style or old-style declaration.
Note, that this declaration is significantly different from the modern declaration. K&R declaration does not introduce a prototype for the function, meaning that it doesn't expose the types of the parameters to the outside code.
There is no difference, it is just that that is the old syntax for function declarations in C -- it was used pre ANSI. Never write such code unless you plan to give it to your friends from the 80's. Also, never depend upon implicit type assumptions (as another answer seems to suggest)
While the old syntax for function definition still works (with warnings, if you ask your compiler), using them does not provide function prototypes.
Without function prototypes the compiler will not check if the functions are called correctly.
#include <stdio.h>
int foo(c)
int c;
{ return printf("%d\n", c); }
int bar(x)
double x;
{ return printf("%f\n", x); }
int main(void)
{
foo(42); /* ok */
bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */
return 0;
}
When the program is run, the output on my machine is
$ gcc proto.c
$ gcc -Wstrict-prototypes proto.c
proto.c:4: warning: function declaration isn’t a prototype
proto.c:10: warning: function declaration isn’t a prototype
$ ./a.out
42
0.000000
Its just the same but old fashion. You probably found it is some old, legacy code.
Old or not, I would argue what is old and what not.. like the pyramids are ancient, but none of today’s so-called scientists have a clue how they were made. Looking back, old programs still work today without memory leaks, but these "new" programs tend to fail more than often. I see a trend here.
Probably they saw functions as structs which have an executable body. Knowledge of ASM is needed here to solve the mystery.
Edit, found a macro which indicates you do not need to supply argument names at all.
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
Here is an usage example, library is zlib-1.2.11.
ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
So my second guess would be for function overloading, otherwise these arguments had no use. One concrete function, and now infinite amount of functions with same name.
I'm relatively new to C. I've come across a form of function syntax I've never seen before, where the parameter types are defined after that parameter list. Can someone explain to me how it is different than the typical C function syntax?
Example:
int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
That's the old-style syntax for parameter lists, which is still supported. In K&R C you could also leave off the type declarations and they would default to int. i.e.
main(argc, argv)
char *argv[];
{
return 0;
}
would be the same function.
What's also interesting is the calling convention difference of functions with, and functions without a prototype. Consider an old style definition:
void f(a)
float a; {
/* ... */
}
In this case, the calling convention is that all arguments are promoted before being passed to the function (for example, a float argument is first promoted to double, before being passed). So if f receives a double but the parameter has type float (which is perfectly valid) the compiler has to emit code that converts the double to a float prior to executing the function's body.
If you include a prototype, the compiler does not do such automatic promotions anymore and any data passed is converted to the types of the parameters of the prototype as if by assignment. So the following is not legal and results in undefined behavior:
void f(float a);
void f(a)
float a; {
}
In this case, the function's definition would convert the submitted parameter from double (the promoted form) to float because the definition is old-style. But the parameter was submitted as a float, because the function has a prototype. For example, clang gives
main.c:3:9: warning: promoted type 'double' of K&R function parameter is not compatible with the parameter type 'float' declared in a previous prototype [-Wknr-promoted-parameter]
Your options of solving the contradictions are the two following:
// option 1
void f(double a);
void f(a)
float a; {
}
// option 2
// this declaration can be put in a header, but is redundant in this case,
// since the definition exposes a prototype already if both appear in a
// translation unit prior to the call.
void f(float a);
void f(float a) {
}
Option 2 should be preferred if you have the choice because it gets rid of the old style definition up front. If such contradicting function types for a function appears in the same translation unit, the compiler will usually tell you (but is not required). If such contradictions appear over multiple translation units, the error will possibly go unnoticed and can result in hard to predict bugs. It is best to avoid these old style definitions.
This is the so caller K&R style or old-style declaration.
Note, that this declaration is significantly different from the modern declaration. K&R declaration does not introduce a prototype for the function, meaning that it doesn't expose the types of the parameters to the outside code.
There is no difference, it is just that that is the old syntax for function declarations in C -- it was used pre ANSI. Never write such code unless you plan to give it to your friends from the 80's. Also, never depend upon implicit type assumptions (as another answer seems to suggest)
While the old syntax for function definition still works (with warnings, if you ask your compiler), using them does not provide function prototypes.
Without function prototypes the compiler will not check if the functions are called correctly.
#include <stdio.h>
int foo(c)
int c;
{ return printf("%d\n", c); }
int bar(x)
double x;
{ return printf("%f\n", x); }
int main(void)
{
foo(42); /* ok */
bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */
return 0;
}
When the program is run, the output on my machine is
$ gcc proto.c
$ gcc -Wstrict-prototypes proto.c
proto.c:4: warning: function declaration isn’t a prototype
proto.c:10: warning: function declaration isn’t a prototype
$ ./a.out
42
0.000000
Its just the same but old fashion. You probably found it is some old, legacy code.
Old or not, I would argue what is old and what not.. like the pyramids are ancient, but none of today’s so-called scientists have a clue how they were made. Looking back, old programs still work today without memory leaks, but these "new" programs tend to fail more than often. I see a trend here.
Probably they saw functions as structs which have an executable body. Knowledge of ASM is needed here to solve the mystery.
Edit, found a macro which indicates you do not need to supply argument names at all.
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
Here is an usage example, library is zlib-1.2.11.
ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
So my second guess would be for function overloading, otherwise these arguments had no use. One concrete function, and now infinite amount of functions with same name.
This question already has answers here:
What should main() return in C and C++?
(19 answers)
Why is the type of the main function in C and c++ left to the user to define? [duplicate]
(6 answers)
Closed 9 years ago.
I am currently learning C and I have written many small programs. However, I have noticed that the main function could start as
main()
{
//code
}
or
int main()
{
//code
return 0;
}
or
int main(void)
{
//code
return 0;
}
Which option should I use? Thanks!
For Standard C
For a hosted environment (that's the normal one), the C99 standard
says:
5.1.2.2.1 Program startup
The function called at program startup is named main. The implementation declares no prototype for this function. It shall be
defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they
are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent;9) or in some other implementation-defined manner.
9) Thus, int can be replaced by a typedef name defined as int, or the type of argv can be written as char **argv, and
so on.
This (is valid in C89) main() implicitly meant (previously) int main(void). However the default return type rule has been abandoned in C99. Also:
main() means - a function main taking an unspecified number of arguments of.
main(void) means "a function main taking no arguments.
Your first example uses a feature inherited from the outdated dialect of C which predated the first ANSI(1989) and ISO(1990) standard: namely, that you can write a function which doesn't specify its return type, and in that case the type defaults to int.
In early C, the void keyword and associated type did not exist. When programmers wanted to write procedures ("functions that have a side effect, but do not return anything"), they simulated it using this feature. They wrote a function without any keyword specifying the return type. They allowed the function to execute to it last statement without returning a value (or alternatively, they used return; to exit from the middle without supplying a value), and they wrote the calls to the function such that those calls did not try to use the return value:
parse_input() /* similar to a procedure in Pascal, but fake! */
{
/* ... */
if (condition())
return; /* no value */
/* ... */
/* fall off end here */
}
int main()
{
parse_input(); /* no return value extracted, everything cool! */
return 0;
}
Unfortunately, some programmers also started not caring about the termination status of a program and writing main itself in this procedure style:
main()
{
/* do something */
/* fall off the end without returning a value */
}
(A mixed style also existed: omitting the int declarator but returning an integer value.)
These programs failing to return a value had an indeterminate termination status. To the operating system, their execution could look successful or failed. Woe to the script writer who tried to depend on the termination status of such a program!
Then things took a turn for the worse. C++ came along and introduced void, and it was adopted into C. With the void keyword in C++, one could declare a function that actually returns nothing (and make it an error to have a return; statement in any other kind of function). The dummy programmers who used to write main with no return type got dumber, and started sticking this new-fangled, fresh-out-of-C++ void in front:
void main() /* yikes! */
{
/* do something */
/* fall off the end without returning a value */
}
By this time they had forgotten that when they wrote main(), it actually meant int main(), which made the function have a compatible type with the startup call invoked by the environment (except for the matter of neglecting to return a value). Now they actually had a different function type from the expected one, which might not even be successfully called!
Where things stand now is that in C++ and in the latest C++ standard, main is still required to return an int. But both languages make a concession for the original dummy programmers: you can let execution "fall off" the end of main and the behavior is as if return 0; had been executed there. So this trivial program now has a successful termination status as of C99 and, I think, C++98 (or possibly earlier):
int main()
{
}
But neither language makes a concession for the second-generation dumber programmers (and everyone else who read the C books that those programmers wrote in the 1980's and since). That is, void is not a valid return declarator for main (except where it is documented by platforms as being accepted, and that applies to those platforms only, not to the portable language).
Oh, and allowance for the missing declarator was removed from C in C99, so main() { } is no longer correct in new dialects of C, and isn't valid C++. Incidentally, C++ does have such a syntax elsewhere: namely, class constructors and destructors are required not to have a return type specifier.
Okay, now about () versus (void). Recall that C++ introduced void. Furthermore, though C++ introduced void, it did not introduce the (void) argument syntax. C++ being more rigidly typed introduced prototype declarations, and banished the concept of an unprototyped function. C++ changed the meaning of the () C syntax to give it the power to declare. In C++, int func(); declares a function with no arguments, whereas in C, int func(); doesn't do such a thing: it declares a function about which we do not know the argument information. When C adopted void, the committee had an ugly idea: why don't we use the syntax (void) to declare a function with no arguments and then the () syntax can stay backward compatible with the loosey-goosey legacy behavior pandering to typeless programming.
You can guess what happened next: the C++ people looked at this (void) hack, threw up their arms and copied it into C++ for the sake of cross-language compatibility. Which in hindsight is amazing when you look at how the languages have diverged today and basically no longer care about compatibility to that extent. So (void) unambiguosly means "declare as having no arguments", in both C and C++. But using it in C++ code that is obviously pure C++ never intended to be C is ugly, and poor style: for instance, on class member functions! It doesn't make much sense to write things like class Foo { public: Foo(void); virtual ~Foo(void) /*...*/ };
Of course, when you define a function like int main() { ... }, the function which is defined has no arguments, regardless of which language it is in. The difference is in what declaration info is introduced into the scope. In C we can have the absurd situation that a function can be fully defined, and yet not declared, in the same unit of program text!
When we write main, usually it is not called from within the program, and so it doesn't matter what the definition declares. (In C++, main must not be called from the program; in C it can be). So it is immaterial whether you write int main() or int main(void), regardless of whether you're using C or C++. The thing which calls main does not see any declaration of it (that you write in your program, anyway).
So just keep in mind that if you write:
int main() /* rather than main(void) */
{
}
then although it is perfect C++ and correct C, as C it has a slight stylistic blemish: you're writing an old-style pre-ANSI-C function that doesn't serve as a prototype. Though it doesn't functionally matter in the case of main, you may get a warning if you use some compilers in a certain way. For instance, GCC, with the -Wstrict-prototypes option:
test.c:1:5: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
Because -Wstrict-prototypes is a darn useful warning to turn on when programming in C, for improved type safety, (along with -Wmissing-prototypes), and we strive to eliminate warnings from our compile jobs, it behooves us to write:
int main(void) /* modern C definition which prototypes the function */
{
}
which will make that diagnostic go away.
If you want main to accept arguments, then it is int main(int argc, char **argv) where the parameter names are up to you.
In C++, you can omit parameter names, so this definition is possible, which serves nicely in the place of main().
int main(int, char **) // both arguments ignored: C++ only
{
}
Since the argument vector is null-pointer-terminated, you don't need argc, and C++ lets us express that without introducing an unused variable:
#include <cstdio>
int main(int, char **argv) // omitted param name: C++ only
{
// dump the arguments
while (*argv)
std::puts(*argv++);
}
first :
declares a function main - with no input parameters. Although main should have returns ( your compiler will take care of this )
2nd/3rd:
Declare a function main which returns an int and takes in no input parameters
You should use 3rd format. Rather this is the best way:
int main(int argc, char *argv[]){
return 0;
}
You should use 1 one of these 4 choices:
int main(void);
int main();
int main(int argc, char **argv);
int main(int argc, char *argv[]);
where it's conventional to use the names argc and argv; you can change them but don't.
Take care never to use void main(void); which is too-often seen in production code.
By default main function returns an integer type, hence its "int main()" or you can give simply "main()"
"main(void)" is same as "main()", it tells the compiler that main function has no arguments.
In case if you want to pass arguments via main function:
int main(int argc, char *argv[]){
return 0;
}
main(){}
The above line give you an error. The default return type of any function in c is int. As the above code return nothing it gives you an error.
int main(){
//body
return 0;
}
In above code it fulfill all requirement so the above code will run.In above code we pass no argument in the function. So this function can take global and local variables to process.
int main(void)
{
//code
return 0;
}
In above code we pass no argument in the function. But specifying void tells the compiler that it does not take any argument. void is the default datatype of argument that signifies no input.
Say I have a function that should accept any number of parameters, so what im coing here is declaring no prototype, and letting the function to be created when it is called in the code. I am using a pointer to void to receive the random number of parametersparameters, however, when doing this, the reference to the memory addres of the first parameter is the only thing that is passed, so for it to work, i would have to declare variables in the same order that i am going to call them in the code:
unsigned char result=0;
unsigned char a=1;
unsigned char b=2;
unsigned char c=3;
char main (void)
{
for (;;)
{
result = function (&a, &b, &c);
result = function (&c, &b, &a);
}
}
function (void *vPointer)
{
return (1);
}
Also I am declaring function without a type since it would not match the call (where it is implicitly declared also).
The result here is a reference to the first parameter sent in the function, so if i point to the next addres in the first function call, it would work, but in the second call, it gets the reference to c, and whatever memory is ahead of where it is placed.
Anyone know a way of sorting the parameters references the correct way? or an effective way to receive an unknown number of parameters in a function?
NOTE: (...) SHALL NOT be used.
All C functions should have prototypes. They're not actually mandatory, but there's no good reason not to use them (unless you're stuck with a pre-ANSI compiler that doesn't support them). (But see the bottom of this answer.)
If you want a function that takes a variable number of arguments, that prototype should end with , ..., and the function itself should use the <stdarg.h> mechanism to process its arguments. (This requires at least one argument with a defined type; that argument is used as an anchor for the following arguments.) It's documented here and elsewhere.
As I was typing this, you updated your question with "NOTE: No libraries (such as (...) )should be used". <stdarg.h> is one of the handful headers that's required for all conforming C implementations, including freestanding (embedded) ones -- because it doesn't define any functions, just types and macros. Your C implementation should support it. If it doesn't, then it's not a conforming C implementation, and you'll need to tell us exactly what compiler you're using and/or read its documentation to find out how it handles variadic functions, or an equivalent.
If you really can't use , ... and <stdarg.h>, (or perhaps the older <varargs.h>), then you can define your function with a fixed number of arguments, enough for all uses, then have callers pass extra null pointers.
EDIT:
This is an update based on new information in comments and chat.
The OP has a homework assignment to implement printf for some TI microcontroller, for some reason not using either the , ... notation or <stdarg.h>. The compiler in question apparently implements C89/C90, so it does support both features; this is an arbitrary restriction.
This information should have been in the question, which is why I'm downvoting it until the OP updates it.
There is no portable way to achieve this -- which is exactly why , ... is part of the standard language, and <stdarg.h> is part of the standard library.
Probably the best approach would be to write a program that uses , ... and <stdarg.h>, then invoke the compiler so it shows just the output of the preprocessor (resolving the various va_* macros and the va_list type), and then imitate that. And you'd have to assume, or verify using the compiler documentation, that the calling convention for variadic and non-variadic functions is compatible. In other words, find out what this particular implementation does, and reinvent a similar wheel.
(I hope that the point of the homework assignment is to demonstrate how much better the standard techniques are.)
UPDATE 2:
I wrote above that all C functions should have prototypes. This may actually be a rare exception to this rule. At least one of these calls:
printf("Hello\n");
printf("x = %d\n", 42);
must produce a diagnostic from a conforming compiler unless either printf is declared with , ... (which is forbidden by the homework assignment), or there is no visible prototype for printf. If there's no prototype, then at least one of the calls will have undefined behavior (behavior that's not defined by the C standard, though it may be defined by a particular compiler).
In effect, to meet the homework requirements, you'll have to pretend that you're using a pre-ANSI C compiler.
the only "clean" way to use functions with variable arguments is to use variadic functions:
#include <stdarg.h>
void myfun(int foo, ...) {
va_list ap;
va_start(foo, ap);
// ...
va_end(ap);
}
you will need to make sure that you know which arguments you actually expect (usually you either use your first argument to indicate how many (and which) arguments to expect (examples are an int that says "now come arguments", or a format-string like "%d %s:%s", that says now come an int and two char*), or you use a a final terminating argument (e.g. read arguments until you encounter NULL).
You could use an array of variable length:
unsigned char result=0;
unsigned char a=1;
unsigned char b=2;
unsigned char c=3;
function (int len, void *vPointer);
int main (void)
{
for (;;)
{
unsigned char args[3];
args[0] = a;
args[1] = b;
args[2] = c;
result = function (3, args);
args[0] = c;
args[1] = b;
args[2] = a;
result = function (3, args);
}
return 0;
}
function (int len, void *vPointer)
{
return (1);
}
But I recommend you use the standard way instead, i.e. variadic functions.
//jk
You can use a structure:-
typedef struct _Params {
int m_a;
int m_b;
int m_c;
} Params;
Then your parameters can't get mixed up. Just as more letters up to the max you need.