求助:输入数字打印置位比特及对应位整数的C程序循环调试
问题分析与解决方案
原代码的核心问题
- 递归函数中的
list是局部数组,每次递归调用都会重新分配内存,之前存储的二进制位不会保留到后续调用,数组内实际是随机值,这是输出异常的根本原因。 - 循环条件
i < 5,但判断i == 5永远不会触发,对应32位的逻辑完全无效。 - 二进制位与权值的对应逻辑错误:比如数字12的二进制是
1100,对应权值8(2³)、4(2²),但原代码的索引与权值映射完全错位,无法正确匹配置位的位。 - 变量
y无实际作用,你需要的是“位值+1”的输出,直接拼接即可,不需要额外变量。
修正方案1:非递归实现(更简洁高效)
直接遍历每一位的权值,判断是否置位后输出:
#include <stdio.h> void print_set_bits(unsigned n) { int first_output = 1; // 从最高位到最低位遍历unsigned的所有位(32位足够覆盖) for (int i = 31; i >= 0; i--) { unsigned int bit_weight = 1U << i; // 计算当前位的权值 if (n & bit_weight) { if (!first_output) { printf(" "); // 非首个输出前加空格 } printf("%d1", bit_weight); // 输出权值+1 first_output = 0; } } printf("\n"); } int main() { unsigned int num; printf("请输入数字:"); scanf("%u", &num); print_set_bits(num); return 0; }
逻辑说明:
1U << i生成第i位的权值(比如i=3时是8,i=2时是4)n & bit_weight判断该位是否为1(置位)first_output控制空格输出,避免多余空格
修正方案2:保留递归逻辑(修复局部变量问题)
如果坚持用递归,需要将数组和索引作为参数传递,让所有递归调用共享同一存储:
#include <stdio.h> // 递归存储二进制位,数组和索引通过参数传递 void bin(unsigned n, char list[], int *index) { if (n > 1) { bin(n / 2, list, index); } list[(*index)++] = n % 2; } void print_set_bits(unsigned n) { char bit_list[32]; // 存储二进制位,足够容纳unsigned的所有位 int count = 0; bin(n, bit_list, &count); int first_output = 1; // 遍历存储的二进制位,计算对应权值 for (int i = 0; i < count; i++) { if (bit_list[i] == 1) { unsigned int bit_weight = 1U << (count - 1 - i); if (!first_output) { printf(" "); } printf("%d1", bit_weight); first_output = 0; } } printf("\n"); } int main() { unsigned int num; printf("请输入数字:"); scanf("%u", &num); print_set_bits(num); return 0; }
逻辑说明:
- 递归时通过指针传递索引,确保所有调用共享同一个数组和计数
- 数组中存储的是从高位到低位的二进制位,计算权值时需要调整索引对应关系
内容的提问来源于stack exchange,提问作者Abyss Auction
相关产品推荐
相关产品推荐

