我已经定义了一个具有初始值的变量 单步执行代码时:
发生了什么事?
注意:这是针对常见问题的参考问题。如果此处的通用答案对您没有帮助,请发布问题,其中包含完整的实际代码。 子>
答案 0 :(得分:15)
变量可能无法保留值的原因有多种。虽然有些是神秘的并且难以调试,但一些最常见的原因包括:
变量由中断修改
//---in main()---
unint8_t rxByte = 0;
printf("%d", rxByte); //prints "0"
//---later in Uart0_Rx_Handler()---
rxByte = U0RXREG; //rxByte set to (for example) 55
//---later in main()---
printf("%d", rxByte); //still prints "0"!!!
如果变量被中断处理程序修改,则需要将其声明为 volatile 。 Volatile让编译器知道变量可以异步修改,并且不应该在寄存器中使用缓存副本。
//---in main()---
volatile unint8_t rxByte = 0;
printf("%d", rxByte); //prints "0"
//---later in Uart0_Rx_Handler()---
rxByte = U0RXREG; //rxByte set to 55
//---later in main()---
printf("%d", rxByte); //corectly prints 55
超越数组的界限
C中没有检查以防止超出数组的范围。
int array[10];
int my_var = 55;
printf("%d", my_var); //prints "55"
for(i=0; i<11; i++) // eleven is one too many indexes for this array
{
array[i] = i;
}
printf("%d", my_var); // prints "11"!!!
在这种情况下,我们循环11次,这是一个比数组大的索引。在大多数编译器中,这将导致覆盖在数组之后声明的变量(页面上的任何地方,甚至不必在下一行声明它们)。这种情况可能发生在许多不同的情况下,包括多维数组和堆栈损坏。
忘记取消引用指针
虽然无关紧要,但在进行分配时忘记指针上的星号不会正确设置变量
int* pCount;
pCount = 10; //forgot the asterisk!!!
printf("%d", *pCount); //prints ??
屏蔽具有相同名称的变量
在内部作用域中重用变量名(如if / for / while块内部或函数内部)会在其他地方隐藏具有相同名称的变量。
int count = 10; //count is 10
if(byteRecevied)
{
int count = U0RXREG; //count redeclared!!!
DoSomething(count);
printf("%d", count); //prints "55"
}
printf("%d", count); //prints "10"
答案 1 :(得分:7)
我想为Zack的优秀答案添加另一个可能的理由。
<强>优化强>
这个经常给我带来惊喜。一个好的优化编译器会注意到两个不同的变量从不同时使用,并且通过在内存中为这些变量提供相同的地址来优化程序。当您单步执行代码时,您可能会在监视窗口中看到一个明显发生变化的变量。但真正发生的是共享其地址的变量正在被写入。
编译器提取的另一个技巧就是摆脱它认为不必要的变量。有时你可能在你的代码中做了相同的事情:
force_a = mass_a * acceleration_a
force_b = mass_b * acceleration_b
total_force = force_a + force_b
编译器发现没有真正需要变量 force_a 和 force_b ,因此将代码更改为:
total_force = (mass_a * acceleration_a) + (mass_b * acceleration_b)
您永远不会看到 force_a 和 force_b 正在进行更新,但您仍然可以将它们添加到观察窗口。
当我单步执行我的程序时,我确信某个变量或其他变量有错误的值,但当我让程序运行而没有步进时,它似乎工作。检查一下这是不是发生在你身上。
<强>加了:强>
Ashish Kulkarni提到,您可以通过关闭优化来检查。