'while' 循环后 int 变量变为 1

int variable changes to 1 after 'while' loop

我正在尝试制作一个 'decimal to binary' 程序。它应该只从 0 转换为 255,而且确实如此。

我有两个变量,'n' 和 'temp',当用户第一次输入数字时,我将其存储在 'n' 上。然后我将 'n' 分配给 'temp'(从而创建一个副本,至少我认为我正在这样做)。

那么我只在我的代码中使用 'temp'。我从不使用 'n',直到最后我决定打印用户输入的数字。问题来了,如果我输入一个大于 255 的数字,变量 'n' 变为 1。

我尝试 运行 通过几个 C 在线编译器编译我的代码,它们都以正确的方式输出变量 'n',这意味着尽管当数字大于255(按预期)他们打印输入的值。

我找到了一个在线编译器,如果它大于 255,它不会打印 'n' 变量。

https://www.tutorialspoint.com/compile_c_online.php

如果你 运行 我的代码通过这个编译器,你会看到变量 'n' 如何在没有被使用的情况下变为 1。

我知道如果您使用大于 255 的数字,'binary part' 将不起作用。我想知道为什么 'n' 突然改变。

#include <stdio.h>

int main()
{
    int bin[8] = {0, 0, 0, 0, 0, 0, 0, 0};
    int arrSize = 7;
    int n;
    int temp;

    scanf("%d", &n);

    temp = n;

    while(temp != 0)
    {
        bin[arrSize] = temp % 2;

        temp = temp / 2;
        arrSize = arrSize - 1;
    }

    printf(" Decimal: %d ----> binary: ", n);
    for(int i = 0; i <= 7; i++)
    {
        printf("%d", bin[i]);
    }
    printf("\n");


    return 0;
}

您已经 运行 完成了 "Buffer overflow"。 对此的快速定义:

A buffer overflow occurs when a program or process attempts to write more data to a fixed length block of memory, or buffer, than the buffer is allocated to hold. Since buffers are created to contain a defined amount of data, the extra data can overwrite data values in memory addresses adjacent to the destination buffer unless the program includes sufficient bounds checking to flag or discard data when too much is sent to a memory buffer.

您的代码中的错误仍然存​​在于此 while 循环中:

while(temp != 0){
   //I added this line to make it clear
   printf("inside loop\tarrSize=%d\n",arrSize);
   bin[arrSize] = temp % 2;
   temp = temp / 2;
   arrSize = arrSize - 1;
}

对于等于 300 的输入(每个输入 > 255 时都会发生错误),您将得到以下输出:

inside loop arrSize=7
inside loop arrSize=6
inside loop arrSize=5
inside loop arrSize=4
inside loop arrSize=3
inside loop arrSize=2
inside loop arrSize=1
inside loop arrSize=0
inside loop arrSize=-1
inside loop arrSize=0

问题是我们有一个索引等于-1,你会问会发生什么?事实上,数组是指向 table 的第一个元素地址 + 偏移量(索引 * table 类型的大小)的指针,这意味着对于 bin[-1] 它在事实上 arrSize,而 bin[-2] 实际上是 n。 您可以通过如下所示验证地址来检查这一点:

printf("@ of bin[-1]:\t%p\n",(void*)&bin[-1]);
printf("@ of arrSize:\t%p\n\n",(void*)&arrSize);
printf("@ of bin[-2]:\t%p\n",(void*)&bin[-2]);
printf("@ of n:\t\t\t%p\n",(void*)&n);

我的编译器给了我:

@ of bin[-1]:   0x7ffe00e32f9c
@ of arrSize:   0x7ffe00e32f9c

@ of bin[-2]:   0x7ffe00e32f98
@ of n:         0x7ffe00e32f98

所以你在不知道bin[-1](或根据n的值的bin[-2])的情况下进行更改,实际上是arrSize(或n)..

如何解决这个问题?我建议您每次要遍历数组时都验证索引(循环的条件必须在 arrSize 的函数中)。或者,如果您希望这个特定示例忽略它并专注于逻辑:验证输入(在您的情况下,输入 n 必须是:0 <= n <= 255

void *ieee2b(double value,char size,void *res){
  char
    *p0=res,
    *p=p0;

  vbreplacec(vbsprintf(p,"%*.*s",size,size," "),' ','0',p);
  if((long)value!=value)
    while(1){
      double
        tmp=value*2;

      *p++='0'+(long)tmp;
      if(tmp==1||tmp==0||p-p0>size)
        break;
      value=tmp-(long)tmp;
    }
  else{
    p=p0+size-1;

    while((long)value>1){
      *p--='0'+((long)value%2);
      value=(long)value/2;
    }
    *p--='0'+((long)value);
  }
  return res;
}