Introduction to working with variables and expressions
This page introduces different methods for looking at variables and introduces some related concepts.
Briefly about working with variables and expressions
There are several methods for looking at variables and calculating their values. These methods are suitable for basic debugging:
Tooltip watch—in the editor window—provides the simplest way of viewing the value of a variable or more complex expressions. Just point at the variable with the mouse pointer. The value is displayed next to the variable.
The Auto window displays a useful selection of variables and expressions in, or near, the current statement. The window is automatically updated when execution stops.
The Locals window displays the local variables, that is, auto variables and function parameters for the active function. The window is automatically updated when execution stops.
The Watch window allows you to monitor the values of C-SPY expressions and variables. The window is automatically updated when execution stops.
The Live Watch window repeatedly samples and displays the values of expressions while your application is executing. Variables in the expressions must be statically located, such as global variables.
The Statics window displays the values of variables with static storage duration. The window is automatically updated when execution stops.
The Macro Quicklaunch window and the Quick Watch window give you precise control over when to evaluate an expression.
The Symbols window displays all symbols with a static location, that is, C/C++ functions, assembler labels, and variables with static storage duration, including symbols from the runtime library.
These additional methods for looking at variables are suitable for more advanced analysis:
The Data Log window and the Data Log Summary window display logs of accesses to up to four different memory locations you choose by setting data log breakpoints. Data logging can help you locate frequently accessed data. You can then consider whether you should place that data in more efficient memory.
The Data Sample window displays samples for up to four different variables. You can also display the data samples as graphs in the Sampled Graphs window. By using data sampling, you will get an indication of the data value over a length of time. Because it is a sampled value, data sampling is best suited for slow-changing data.
For more information about these windows, see The application timeline.
C-SPY expressions
C-SPY expressions can include any type of C expression, except for calls to functions. The following types of symbols can be used in expressions:
Assembler symbols (register names and assembler labels)
Expressions that are built with these types of symbols are called C-SPY expressions and there are several methods for monitoring these in C-SPY. Examples of valid C-SPY expressions are:
i + j i = 42 myVar = cVar cVar = myVar + 2 #asm_label #R2 #PC my_macro_func(19)
If you have a static variable with the same name declared in several different functions, use the notation function::variable to specify which variable to monitor. For global variables (variables defined in file scope), you can use the notation module\variable—the same syntax that is used to denote variables in the Statics window. For example, if there are two source files source_a.c and source_b.c, each with an identical static int var = 0; definition, you can write source_a\var or source_b\var to specify a specific variable.
C/C++ symbols
C symbols are symbols that you have defined in the C source code of your application, for instance variables, constants, and functions (functions can be used as symbols but cannot be executed). C symbols can be referenced by their names. Note that C++ symbols might implicitly contain function calls which are not allowed in C-SPY symbols and expressions.
Note
Some attributes available in C/C++, like volatile, are not fully supported by C-SPY. For example, this line will not be accepted by C-SPY:
sizeof(unsigned char volatile __memattr *)
However, this line will be accepted:
sizeof(unsigned char __memattr *)
Assembler symbols
Assembler symbols can be assembler labels or registers, for example the program counter, the stack pointer, or other CPU registers. If a device description file is used, all memory-mapped
peripheral units, such as I/O ports, can also be used as assembler symbols in the same way as the CPU registers. See Modifying a device description file.
Assembler symbols can be used in C-SPY expressions if they are prefixed by #.
Example | What it does |
|---|---|
| Increments the value of the program counter. |
| Assigns the current value of the stack pointer register to your C-SPY variable. |
| Sets |
| Sets |
In case of a name conflict between a hardware register and an assembler label, hardware registers have a higher precedence. To refer to an assembler label in such a case, you must enclose the label in back quotes ` (ASCII character 0x60). For example:
Example | What it does |
|---|---|
| Refers to the program counter. |
| Refers to the assembler label |
Which processor-specific symbols are available by default can be seen in the Registers window, using the CPU Registers register group. See Registers window.
C-SPY macro functions
Macro functions consist of C-SPY macro variable definitions and macro statements which are executed when the macro is called.
For information about C-SPY macro functions and how to use them, see Briefly about the macro language.
C-SPY macro variables
Macro variables are defined and allocated outside your application, and can be used in a C-SPY expression. In case of a name conflict between a C symbol and a C-SPY macro variable, the C-SPY macro variable will have a higher precedence than the C variable. Assignments to a macro variable assign both its value and type.
For information about C-SPY macro variables and how to use them, see Reference information on the macro language.
Using sizeof
According to standard C, there are two syntactical forms of sizeof:
sizeof(type) sizeofexpr
The former is for types and the latter for expressions.
Note
In C-SPY, do not use parentheses around an expression when you use the sizeof operator. For example, use sizeof x+2 instead of sizeof (x+2).
Limitations on variable information
The value of a C variable is valid only on step points, that is, the first instruction of a statement and on function calls. This is indicated in the editor window with a bright green highlight color. In practice, the value of the variable is accessible and correct more often than that.
When the program counter is inside a statement, but not at a step point, the statement or part of the statement is highlighted with a pale variant of the ordinary highlight color.
Effects of optimizations
The compiler is free to optimize the application software as much as possible, as long as the expected behavior remains. The optimization can affect the code so that debugging might be more difficult because it will be less clear how the generated code relates to the source code. Typically, using a high optimization level can affect the code in a way that will not allow you to view a value of a variable as expected.
Consider this example:
myFunction()
{
int i = 42;
...
x = computer(i); /* Here, the value of i is known to C-SPY */
...
}From the point where the variable i is declared until it is actually used, the compiler does not need to waste stack or register space on it. The compiler can optimize the code, which means that C-SPY will not be able to display the value until it is actually used. If you try to view the value of a variable that is temporarily unavailable, C-SPY will display the text:
Unavailable
If you need full information about values of variables during your debugging session, you should use the lowest optimization level during compilation, that is, None.