Search code examples
cpointersmicrocontrollervoid-pointersfunction-declaration

Pointer to void as an argument in a function with no prototype for variable number of arguments


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.


Solution

  • 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.