C语言中无符号数字节数组相加丢失末尾进位问题排查
C大数加法末尾进位丢失及数组访问错误修复
问题分析
你的代码存在两个关键问题,直接导致加法异常:
数组访问语法错误:
*left[i]的写法不符合指针数组的访问逻辑。left是BIG_INT*(即unsigned char (*)[8]),left[i]会被解析为第i个BIG_INT数组,而非当前数组的第i个元素。正确的访问方式应该是(*left)[i]——先解引用指针得到目标数组,再访问其第i个元素。这个错误会导致越界读写内存,最终出现全0的错误结果。未处理最终进位:循环结束后如果
carry为1,说明加法产生了最高位进位,但当前代码没有将这个进位写入大数(若大数还有剩余空间)。不过在你的测试场景中,数组访问错误是导致结果异常的直接原因。
另外还有两个潜在问题:
buffer类型使用char可能引发符号扩展问题,建议改为unsigned char;- 循环变量使用
int64_t没必要,用int即可(因为数组大小仅为8)。
修复后的代码
#include <stdlib.h> #include <stdio.h> #include <string.h> #define BIG_INT_SIZE 8 typedef unsigned char BIG_INT[BIG_INT_SIZE]; int add_big_int(BIG_INT *left, size_t right) { if (!right) return 0; unsigned char buffer[sizeof(size_t)]; memcpy(buffer, &right, sizeof(size_t)); unsigned int carry = 0; for (int i = BIG_INT_SIZE - 1; i >= 0; --i) { // 修正数组访问方式,同时确保无符号运算 unsigned int sum = (*left)[i] + buffer[i] + carry; (*left)[i] = sum & 0xff; // 只保留低8位 carry = sum >> 8; } // 如果需要处理溢出(比如BIG_INT_SIZE大于sizeof(size_t)),可以在这里处理carry // 例如:if (carry) { /* 处理最高位进位,比如扩容或返回错误 */ } printf("carry: %u\n", carry); return carry ? -1 : 0; // 返回进位状态,方便上层处理溢出 } int main() { // 初始化BIG_INT为255(低字节在数组最后一位) BIG_INT big = { 0, 0, 0, 0, 0, 0, 0, 0xff }; add_big_int(&big, 1); // 打印结果,验证是否为[0,0,0,0,0,0,1,0] printf("Result: "); for (int i = 0; i < BIG_INT_SIZE; ++i) { printf("%d ", big[i]); } printf("\n"); return 0; }
修复说明
- 修正了数组访问语法:将
*left[i]改为(*left)[i],确保正确读写目标大数的每个字节; - 将
buffer改为unsigned char类型,避免符号扩展影响运算; - 显式用
sum & 0xff赋值给大数元素,明确只保留低8位; - 修改返回值,将进位状态返回给调用者,方便处理溢出场景;
- 调整了
main函数中的大数初始化,正确表示255,测试255+1=256的场景。
运行修复后的代码,结果会输出预期的 [0 0 0 0 0 0 1 0],carry 值为0(因为8字节刚好容纳进位后的结果)。
内容的提问来源于stack exchange,提问作者block103
相关产品推荐
相关产品推荐

