Variables
This page contains declarations of test local variables, and
initialization of global and test local variables. Test local
variables are created on the stack before test execution. They may
be used as function parameters, when pointers or structures are
needed. For example, for function
void initStructT(struct_td * pStruct, long value);
we need the following local variable:
The two buttons between the tables can save us some typing.
The first one copies all declared test local variables to the
initialization table. The second one opens a wizard dialog, which
helps us to add all array or structure members to the
initialization table with few clicks:
Note, that we have to initialize each structure or array member
separately.
Now we can use the declared and initialized variables as function
parameters:
Arrays
For character and number arrays we can specify contents with
single entry. For strings we can use double quotes, for example:
Declaration:
myChar char[10]
Initialization:
myChar "Hello!"
For number arrays we can use curly braces, for example:
Declaration:
myArray int[10]
Initialization:
myArray {10, 20, 30, 40, 50, 60, 70, 80, 90, 100}
Pointers
If function parameter is a pointer, we must make sure to assign
pointer so that it points to valid memory area. For example, if
function declaration is:
void f(int *p);
and we declare variable:
param1 int *
and then 'initialize' it like:
*param1 10 // DON'T DO THIS!!!
then param1 will contain uninitialized address, depending on
previous stack content. Symptoms: test will sometimes succeed,
sometimes fail with error. Proper approach:
Declaration:
param1 int
Initialization:
param1 10
Function parameter:
¶m1
Global variables
Global variables do not need declaration
in testIDEA, because they already exist on the target and
their address and type are already known from debug info. For
example, global variable iCounter
is initialized to
value 10:
Global and function static variables keep their values between
test runs - if a test changes value of the global variable, the
next test will be executed with the changed value.
Warning: If we define type of a variable, it means a
declaration of a local variable. If it has the same name as a
global variable, the global variable is hidden!
Fully qualified names of global variables
When we have multiple download files, global variables from other
then the default download file, require access with fully
qualified name, which includes the download file name:
"<moduleName>#"<varName>,,<downloadFileName>
where:
-
moduleName
- name of the C source file, which
contains the variable (optional)
-
varName
- name of the variable
-
downloadFileName
- name of the download file, where the variable is located
Examples:
"main.c#"iCounter,,executable.elf
iCounter,,executable.elf
When we use such variable in expressions, the download file name
is valid for whole expression, so we have to specify it at the
end of expression, for example:
iCounter == 3,,executable.elf
Function static variables
Syntax for static variables declared inside of a function, is the
following:
<functionName>##<functionStaticVarName>
where:
-
functionName
- name of the function, which
contains static variable
-
functionStaticVarName
- name of the static
variable inside the function
Example:
myFunction##myStaticVar
Variables with the same type as function parameters
This section describes workaround for:
- Incomplete debug information
Sometimes it may happen, that debug information
contains wrong information or the type of function parameter is
not named. For example, if a struct with two integers is
typedefed, and the typedef is used as function parameter, some
compilers do not provide the name of the typedef. In such cases
winIDEA knows the parameter is a struct with two integers, but
does not know the name of the type. This means we can not create a
variable of the same type as function parameter.
- Bug in compiler
- Types declared in header file and included in several
compile units.
This is the most common source of problems with function parameter
types. The reason for this lies in C/C++ design - each time a header
file is included in c/cpp file, a new type is generated, because
compiler does not know if it is the same type which has already been
included in other module. Some compilers/linkers are able to merge
this information in elf symbol info, but some are not, and sometimes
merging is not possible because of C language design.
To solve this problem, we can use types of function parameters
implicitly when creating variables by using
keywords decltype or decltype_ref. The syntax is the
following:
decltype(<functionName>##N)
decltype(*<functionName>##N)[K]
decltype_ref(<functionName>##N)
where:
- functionName - name of the function
- N - index of function parameter, where 0 means function
return value type, 1 is the first parameter, ...
- K - size of the declared array
Examples:
-
If the function is declared as:
void myFunction(MyStruct a)
we can use the following type instead of type MyStruct
:
decltype(myFunction##1)
-
If the function is declared as:
otherFunction(MyType *ptr)
and we want to create an array of 5 elements of type MyType
to
be used as a pointer parameter, we can write:
decltype(*myFunction##1)[5]
Note that type of the first function parameter is MyType
*
. We have to dereference it to get
type MyType
.
-
If the function is declared as:
void f(int n1, int * pn2, int & rn3)
we can get parameter types using one of the following:
Syntax | Returned type | Description |
decltype(f##1) | int | type of 1st parameter (n1) |
decltype(f##2) | int * | type of 2nd parameter (pn2) |
decltype(*f##2) | int | type of pointer |
decltype(*f##2)[3] | int[3] | declares array to be used as the first parameter |
decltype(f##3) | int & | type of param3 (rn3) |
decltype_ref(f##3) | int | referenced type of param3 (rn3) |
Type merging in winIDEA
When types declared in header file are included in several compile
units, then symbol browser in winIDEA shows several types with the
same name. In such case we can select options Optimize type
information or Merge Types in dilaogs opened with Debug
| Files for download:
Option Optimize type information checks some information
before merging types, but sometimes this information is not
available and merging is not performed. On the other hand,
option Merge Types merges types if they have the same
name. This setting should always solve the problem of type merging
for equal types, but it will cause problems if you have types with
the same name, but are actually different. When using this option,
it is your responsibility to be sure about declarations of types
used.