uint8_t十进制转二进制函数失效求助:输入大于3时异常
嘿,我来帮你理清这里的问题——核心是你混淆了「二进制数值存储」和「二进制字符串的十进制表示」,再加上类型溢出的问题,咱们一步步拆解:
你写的dec_to_bin和dec_to_bin2,根本不是在把十进制数转成二进制存储的uint8_t,而是在生成二进制字符串对应的十进制整数:比如输入10,你想得到二进制1010,但函数却把它当成十进制数1010来计算存储。
举个例子,输入3的时候,函数计算(3%2)*1 + (1%2)*10 = 1+10=11——这个11是十进制数,不是二进制的11(二进制11对应的十进制是3)。这完全是把“二进制的每一位”当成“十进制数的每一位”来构建了,逻辑方向错了。
uint8_t是无符号8位类型,取值范围只有0~255。当输入大于3时,比如10,函数生成的十进制数1010远大于255,赋值给uint8_t时会触发溢出截断:1010 % 256 = 242,所以实际存储的是0xF2(二进制11110010)。
而你用的bin_to_dec函数,逻辑是把传入数值的二进制位按顺序拼接成十进制数:比如传入242(二进制11110010),它会把每一位取出来拼成11110010这个十进制数。这个数远超过普通int的取值范围(假设单片机是16位int,最大值是32767),所以溢出后变成负数,就是你看到的-3110。
先明确你的需求,分两种情况处理:
情况1:只是想存储十进制数的二进制值
这根本不需要转换函数!计算机里的数本身就是二进制存储的,直接赋值就行:
uint8_t num = 10; // 变量里自动存储的就是二进制00001010
如果要验证某一位的状态,用位操作就行:
// 检查第3位(从0开始计数)是否为1 if ((num >> 3) & 1) { // 第3位是1,对应二进制的8位权重 }
情况2:想把十进制数转成二进制字符串形式(比如10→"1010")用于LCD显示
这种情况不要用uint8_t存储结果,直接生成字符串更靠谱:
// 把uint8_t的十进制数转成8位二进制字符串,buf需要至少9个字符空间(含结束符) void dec_to_bin_str(uint8_t decimal, char *buf) { for (int i = 7; i >= 0; i--) { buf[7 - i] = ((decimal >> i) & 1) ? '1' : '0'; } buf[8] = '\0'; // 字符串结束符 }
之后直接把这个字符串输出到LCD即可,不需要再通过bin_to_dec转换。
如果一定要用现有的bin_to_dec,那要先修正它的返回类型避免溢出,再直接传入原十进制数的二进制存储值:
// 把uint8_t的二进制位转成对应的十进制字符串数值(比如0b00001010→1010) long bin_to_dec(uint8_t binary) { long result = 0; for (int i = 7; i >= 0; i--) { result = result * 10 + ((binary >> i) & 1); } return result; } // 使用示例 uint8_t num = 10; long display_num = bin_to_dec(num); // 得到1010,可直接输出到LCD
int32_t? 传参类型不是核心问题——如果是存储二进制值,用uint8_t就足够;如果是生成二进制字符串,传uint8_t也能覆盖8位二进制的范围。核心是先把函数逻辑的方向搞对,别再把二进制位当成十进制数来构建了。
内容的提问来源于stack exchange,提问作者david_10001

