linux C位计数导致意外行为

mbyulnm0  于 5个月前  发布在  Linux
关注(0)|答案(2)|浏览(68)

我正在用C写一个Hamming权重函数。我想知道我是否做对了,所以我的计划是在数字5上进行测试。我不想在谷歌上搜索二进制为5,并写了一些代码来自己做,但是当我运行代码时,我得到了这个:

testing code
bit length of 5: 32

five: -1354390872 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0

字符串
这是没有意义的,因为没有任何东西可以输出这么大的负数。

#include <stdio.h>

int main() {
      printf("\ntesting code\n");
      int fv[32];
      int fiv = 5;
      for (int i = 0; i < 32; i++) {
            if (fiv & 1) fv[32 - i] = 1; else fv[32 - i] = 0;
            fiv >>= 1;
      }
      printf("bit length of 5: %ld\n\n", (sizeof(5) * 8));
      printf("five: ");
      for (int i = 0; i < 32; i++) {
            printf("%d ", fv[i]);
      }
      printf("\n");
      return 0;
}


我希望用整数0或1填充数组,其中数组将表示数字的二进制值。它确实用32位整数填充数组,但是-1354390872不是0,也不是1。我试着将数字改为(sizeof(n) * 8以说明字节的大小,然而,这只是挂起,我无法弄清楚,因为没有sizeof()的手册页。我还试图将设置fv[32 - i]的行替换为未优化的混乱:if (fiv & 1) fv[32 - i] = 1; else fv[32 - i] = 0;,希望它会改变输出
有人能帮忙吗,我肯定有一种我不知道的二进制格式,我可以使用,但我真的不知道。
编辑:多次运行代码会给出非常大的数字的完全随机输出。示例:

testing code
bit length of 5: 32

five: -956652888 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
forward:~/cproblem/declareyourvariablesc $ ./main

testing code
bit length of 5: 32

five: -754855256 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
forward:~/cproblem/declareyourvariablesc $ ./main

testing code
bit length of 5: 32

five: 104133288 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
forward:~/cproblem/declareyourvariablesc $ ./main

testing code
bit length of 5: 32

five: -1662766424 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
forward:~/cproblem/declareyourvariablesc $ ./main

testing code
bit length of 5: 32

five: -103538008 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
forward:~/cproblem/declareyourvariablesc $ ./main

testing code
bit length of 5: 32

five: 1071841960 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0

taor4pac

taor4pac1#

@chqrlie已经回答了正确的解决方案。
只是为了解释这里发生的事情:由于fv是在main函数中本地定义的,并且没有设置为零,它的值未定义。您的for循环从0迭代到31,因此您将位置32处的fv的值更改为1。位置32超出范围,结果在未定义的行为。
但特别是位置0从未被写入保持其“随机”值。

eqzww0vc

eqzww0vc2#

你应该使用fv[32 - 1 - i]而不是fv[32 - i]来避免访问数组的末尾。正如发布的那样,代码有未定义的行为,这解释了观察到的输出,但也可能发生其他任何事情。
要使这些计算无效,可以使用向下循环(**注意i--**中使用的后递减运算符):

for (int i = 32; i-- > 0;) {
          if (fiv & 1)
              fv[i] = 1;
          else
              fv[i] = 0;
          fiv >>= 1;
      }

字符串
你可以简化循环体:

for (int i = 32; i-- > 0;) {
          fv[i] = fiv & 1;
          fiv >>= 1;
      }


另请注意,sizeof(5)int类型的字节大小,并且具有可能与unsigned long不同的类型size_tsize_t需要将%zu转换为printf。为了避免遗留系统上的兼容性问题,我建议将size_t表达式转换为(unsigned)并使用%u。还要注意,* 8假设8位字节,这在今天非常普遍,除了一些DSP和古老的CPU。纯粹主义者会使用在<limits.h>中定义的CHAR_BIT
下面是修改后的代码:

#include <stdio.h>

int main(void) {
    printf("\ntesting code\n");

    int fv[32];
    int fiv = 5;

    for (int i = 32; i-- > 0;) {
        fv[i] = fiv & 1;
        fiv >>= 1;
    }
    printf("bit length of 5: %u\n\n", (unsigned)(sizeof(5) * 8));
    printf("five: ");
    for (int i = 0; i < 32; i++) {
        printf("%d ", fv[i]);
    }
    printf("\n");
    return 0;
}

相关问题