Function Calls and Argument Conversions

Function Calls

A function is called with actual arguments placed in the same sequence as their matching formal parameters. Use the function-call operator ():

function_name(expression_1, ... , expression_n)

Each expression in the function call is an actual argument. Number and types of actual arguments should match those of formal function parameters. If types do not match, implicit type conversions rules will be applied. Actual arguments can be of any complexity, but order of their evaluation is not specified.

Upon function call, all formal parameters are created as local objects initialized by the values of actual arguments. Upon return from a function, a temporary object is created in the place of the call, and it is initialized by the expression of the return statement. This means that the function call as an operand in complex expression is treated as a function result.

If the function has no result (type void) or the result is not needed, then the function call can be written as a self-contained expression.

In C, scalar arguments are always passed to the function by value. The function can modify the values of its formal parameters, but this has no effect on the actual arguments in the calling routine. A scalar object can be passed by the address if a formal parameter is declared as a pointer. The pointed object can be accessed by using the indirection operator * .

// For example, Soft_UART_Read takes the pointer to error variable,
// so it can change the value of an actual argument:
Soft_UART_Read(&error);

// The following code would be wrong; you would pass the value
// of error variable to the function:
Soft_UART_Read(error);

Argument Conversions

If a function prototype has not been previously declared, the mikroC PRO for PIC32 converts integral arguments to a function call according to the integral widening (expansion) rules described in Standard Conversions. If a function prototype is in scope, the mikroC PRO for PIC32 converts the passed argument to the type of the declared parameter according to the same conversion rules as in assignment statements.

If a prototype is present, the number of arguments must match. The types need to be compatible only to the extent that an assignment can legally convert them. The user can always use an explicit cast to convert an argument to a type that is acceptable to a function prototype.

  Note : If the function prototype does not match the actual function definition, the mikroC PRO for PIC32 will detect this if and only if that definition is in the same compilation unit as the prototype.
                 If you create a library of routines with the corresponding header file of prototypes, consider including that header file when you compile the library, so that any discrepancies between the prototypes and actual definitions will be detected.

The compiler is also able to force arguments to change their type to a proper one. Consider the following code:

int limit = 32;
char ch = 'A';
long res;

// prototype
extern long func(long par1, long par2);

main() {
  ...
  res = func(limit, ch);  // function call
}

Since the program has the function prototype for func, it converts limit and ch to long, using the standard rules of assignment, before it places them on the stack for the call to func.

Without the function prototype, limit and ch would be placed on the stack as an integer and a character, respectively; in that case, the stack passed to func will not match size or content that func expects, which can cause problems.

Copyright (c) 2002-2012 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!
Want more examples and libraries? 
Find them on LibStock - A place for the code