功能相同的代码,不同的结果

Functionally identical code, different results

本文关键字:结果 代码 功能      更新时间:2023-10-16

我有 2 段代码,它们做完全相同的事情,但其中一段实际上不起作用。 谁能解释为什么?

该代码通过spi将数据发送到运行显示器的FPGA。 我几乎用完了芯片上的代码存储,所以我试图尽可能多地减少。 由于某种原因,下面的更改最终中断了,程序的其余部分与它完全相同。

//Looping to execute code twice doesnt work
for (byte i = 0; i < 3; i++)
{
temp2 = temp % 10;
temp /= 10;
temp2 |= 0x40;
for (byte k = 0; k < 2; k++)
{
SPI.transfer(reg[j]);
delayMicroseconds(10);
SPI.transfer(temp2);
delayMicroseconds(10);
}
reg[j] -= 1;
}

.

//But copy-paste does
for (int i = 0; i < 3; i++)
{
temp2 = temp % 10;
temp /= 10;
temp2 |= 0x40;
SPI.transfer(reg[j]);
delayMicroseconds(10);
SPI.transfer(temp2);
delayMicroseconds(10);
SPI.transfer(reg[j]);
delayMicroseconds(10);
SPI.transfer(temp2);
delayMicroseconds(10);
reg[j] -= 1;
}

最可能的解释是,其他一些代码依赖于满足特定时序约束的这个循环,如果不这样做,就会失败。

您引入的可能影响时间的更改包括:

  • i更改为类型byte而不是int。 这可能会影响时间 -int通常是"本机"类型,通过各种措施可以更有效地操作。 使用byte可能会更改外循环的计时。 例如,如果byte是比int小的类型,则对字节的操作可能涉及与int之间的转换)。
  • 实质上,您已经将重复的语句序列替换为内部循环。根据优化设置,编译器可能会展开循环(实际上生成与第一个代码示例相同的行为),也可能不会。 如果编译器不展开循环,循环构造本身的开销(初始化变量k,在每次迭代时检查和递增它等)会影响代码的计时。

如果依赖于满足特定时序约束的此代码,则需要在某处记录。 如果没有记录需求,我建议您记录它(例如,将其作为特定需求输入),然后记录派生的需求(例如,一个使用int来控制外部循环的要求 [如果需要]和另一个要求在代码中展开内部循环而不是依赖于编译器优化)。

...由于某种原因打破...

从来都不是好事,如果有什么东西"坏了",它会对不同的草图产生不同的影响。

reg[j] -= 1; 

例如,如果这很痛苦,因为 j 是越界的,无论是否存在变量 k,它都可能产生不同的效果。

尝试隔离问题并使其可重现... 我敢打赌问题不在于发布的部分。 ;)

在您的原始帖子中:"...我几乎用完了芯片上的代码存储......"。 你的内存怎么样? 我有一次在自己的代码中看到类似的东西是当我用完 RAM 并且我的变量损坏堆栈或堆栈损坏我的变量时。 请记住,C/C++需要一些"工作"内存来跟踪所有内容。 变量从可用 RAM 的一端分配,堆栈从另一端分配。当您使用过多的 RAM 或函数嵌套得太深时,两者会相互碰撞并相互干扰/损坏。

|************ Available RAM ************|
| Variables >>>>>>>>>>>>>>>>!!<<< Stack |
Variables grow >
Stack grow <
Problem !!