0

所以我按照本教程来熟悉 Arduino。在课程结束时,作者试图通过让我编写一个能够将任何给定 GB 转换为 KB 的程序来测试我对基本数学运算、位和字节的概念以及如何使用适当类型的数据的理解。我认为这是一项简单的任务。但是我想错了。

所以这是我的原始代码:

long drive_gb = 100; //given number
long drive_kb;
void setup()
{
   Serial.begin(9600);

   Serial.print("Your HD is ");
   Serial.print(drive_gb);
   Serial.println(" GB large.");


   drive_kb = 1024*1024*drive_gb;

   Serial.print("It can store ");
   Serial.print(drive_kb);
   Serial.println(" Kilobytes!");

 }

 void loop()
 {
 }

但是当我检查我的串行监视器时,我得到了这个输出:

“你的 HD 有 100 GB 大。它可以存储 0 KB!”

然后我将我的代码修改为:

long drive_gb = 100;
 long drive_kb;
 long drive_mb;
 void setup()

 {
   Serial.begin(9600);

   Serial.print("Your HD is ");
   Serial.print(drive_gb);
   Serial.println(" GB large.");

   drive_mb = 1024*drive_gb;
   drive_kb = 1024*drive_mb;

   Serial.print("It can store ");
   Serial.print(drive_kb);
   Serial.println(" Kilobytes!");

 }

 void loop()
 {
 }

现在我得到正确的输出

“你的 HD 有 100 GB 大。它可以存储 104857600 KB!”

所以我的问题是:

  1. 第一个代码是否导致溢出情况?如何?
  2. 第一个代码在数学上与第二个代码有何不同?

谢谢!

4

3 回答 3

2

要获得明确的答案,您需要列出编译器在第一个示例中生成的汇编代码。

我的猜测是,代码X = 1024 * 1024 * Y;并没有考虑到存储结果需要 long 并且生成的代码使用 int 的事实。

尝试:X = 1024L * 1024L * Y;看看你是否得到正确答案。

于 2013-10-08T23:06:04.760 回答
1
  • 1024*1024*drive_gb意味着(1024*1024)*drive_gb因为,根据 C 标准,乘法是从左到右关联的。
  • 1024意味着(int) 1024因为十进制常量具有第一种可以适合它们的类型(int,long,unsigned long)。
  • 1024*1024作为两个整数的乘积,结果也将是一个整数。
  • 在 Arduino 平台(实际上是 AVR)上,int 是 16 位,因此上述产品溢出。

您只需编写即可得到正确的结果

drive_kb = 1024*(1024*drive_gb);
于 2015-02-16T11:34:59.460 回答
0

如果你想玩溢出,建议要么利用诸如 MAX_INT 之类的常量(如果可用),要么依赖更多特定于系统的类型,如 uint32_t,它明确说明有多少字节/位可用。

于 2015-01-14T11:44:53.273 回答