Device Monitoring Studio supports native functions. A native function is a function defined in the header file that uses the same language syntax.
The following syntax is used to define a function:
optional-attributes
function f_name ( parameter-list )
{
function-body
}
optional-attributes := [ function-attribute [, function-attribute [, …] ] ]
function-attribute := arguments_array | nooptimize
parameter-list := param-name1 [, param-name2 [, … ] ]
function-body := *(variable-declaration | statement)
The function may be declared at any scope (either global or user-defined). Function's name must be unique within a scope. A function can take any number of arguments (or no arguments). It is allowed to pass different number of arguments during a function call. If fewer arguments passed, the rest are undefined, if more arguments passed, extra parameters are ignored.
Only the following constructs are allowed in a function body:
Ability to use any statement allows you to create branches and loops. A return statement sets function's return value and exits function. A function is allowed to have multiple return statements.
A following pseudo-variables are available for a function's body:
parameter_count
arguments_array
Holds values of all passed parameters. The size of the array is parameter_count
. If function has named arguments, both named parameters and values of this array may be used to reference passed parameters.
Note: for performance reasons this array is generated only when arguments_array
attribute is specified before the function's definition.
All parameters are always passed by value. If arguments_array
attribute is specified and a function has named arguments, corresponding array elements and named parameters have copies of values (that is, modifying one does not modify another).
Each function defines its own scope. All variables declared in this scope are destroyed when function execution finishes and re-created next time it is run.
Device Monitoring Studio automatically optimizes constant functions. If it encounters a function that always returns a constant value and is being used with constant arguments, it replaces the function call with a calculated value. That means that all native functions must be immutable, that is, they must not affect any global state.
If you still need to use a function that modifies a global state, use the nooptimize
attribute to suppress function optimization.
Note that function optimization always works at the call site. Consider the following example:
function square(x)
{
return x * x;
}
struct A
{
char array[square(5)]; // will be optimized to 25
int size;
char array2[square(size)]; // will not be optimized
};