I use uVision 4.53 (with Armcc V4.1.0.894), processor STM32F407 with standard settings.
If I compile the following small program:
class Test{ public: static int i1; static int i2; int TestFunc( void); }; int Test::TestFunc( void){ i1= i2; return 0; } Test T; int main( void){ T.TestFunc(); while( 1); }
Then the watch window will show the class element T with the address "0x20000014 &T". This is a bit strange, as the address of i1 is 0x2000001C and address of i2 is 0x20000018 (as you can easily see if you look at the disassembly of the line "i1=i2" in function TestFunc).
If I try to change the value of T1.i1 in the watch window, it will fail - it always keeps zero, even after I enter some changed value.
The miracle happens, if I change the class definition to
class Test{ public: static int i1; static int i2; static int TestFunc( void); };
Then the watch window will show the class element T with the address "0x00000000" (this usually would mean, that T is not used in the software - so this evidently is wrong). But nicely now i1 and i2 can be accessed without problems through the watch window.
I came to this problem through large classes with structs. For structs you clearly see the address in the watch window. There I recognized that the adresses sometimes were complete nonsense (it showed 0x4000000 adresses for normal variables - 0x4000000 is reserved for peripheral registers, so it is impossible).
It seems to be important, that all functions which are invoked from some static C-like funktion (as main()), need to be static. Otherwise the watch window does very strange things.
BTW: It would make a bit sense, if in the "Type" field uVision would show "class T" (now it says "struct T", which is slightly disturbing ...).
I also agree that I don't expect a debugger to show static data members (like 'i1') when viewing an object (like 'T').
But for completeness, and at the risk of muddying the waters, I want to point out that the C++ language allows accessing static members using an object (or pointer or reference) so, given the declaration earlier in the thread and 'Test *tp;', all three of these are the same:
... int x1 = Test::i1; int x2 = T.i1; int x3 = tp->i1;
(The value of the object or pointer is almost certainly ignored at runtime.)