x86-64平台uint64_t跨OS定义差异及适配方案求助
x86-64架构下Linux与Windows的uint64_t定义差异及兼容方案
一、uint64_t定义差异的原因
两大平台的差异源于遵循的C语言数据模型不同:
- Linux等类Unix系统在x86-64架构下采用LP64模型:
long和指针类型为64位,int为32位,因此unsigned long int刚好满足64位无符号整数的要求,被用来定义uint64_t。 - Windows在x86-64架构下采用LLP64模型:为兼容32位旧程序,保留了
long的32位长度,仅将long long和指针扩展为64位,因此只能用unsigned long long int定义uint64_t。
二、跨平台将uint64_t按unsigned long long使用的方案
无需修改系统头文件中的uint64_t定义,通过以下方式实现跨平台兼容:
- 直接显式使用unsigned long long:如果代码需要固定64位无符号类型,直接写
unsigned long long而非依赖uint64_t,该类型在两个平台上均为64位。 - 封装自定义类型别名:统一代码中的64位无符号类型,避免平台差异:
#if defined(_WIN64) || defined(__linux__) typedef unsigned long long my_uint64; #endif
后续代码中统一使用my_uint64即可保证跨平台的64位长度。
- 修正代码潜在风险:检查代码中依赖平台类型的部分,比如你提供的
div_10_big函数中,dec->bits[i] += remained << 32的操作,如果bits成员是unsigned long,在Windows下会因32位长度导致溢出风险。建议将s21_big_decimal的bits数组直接定义为unsigned long long类型,彻底规避平台差异。
三、相关实现代码
二进制除法核心函数
void binary_div(s21_big_decimal *value_1, s21_big_decimal value_2, s21_big_decimal *result) { init_s21_decimal(result); s21_big_decimal Q; s21_big_decimal R; int scaleDiv = -1; do { init_s21_decimal(&R); init_s21_decimal(&Q); scaleDiv++; int lastBit = (SIZE_BIG_DECIMAL - 1) * 32 - 1; int currentBit = get_bit_big(*value_1, lastBit); while (currentBit == 0 && lastBit >= 0) { currentBit = get_bit_big(*value_1, lastBit); if (currentBit == 0) lastBit--; } for (int i = lastBit; i >= 0; i--) { change_left_big(&R, 1); set_bit_big(&R, 0, get_bit_big(*value_1, i)); if (is_less_or_equal_big(value_2, R)) { s21_big_decimal res = {0}; init_s21_decimal(&res); s21_sub_big(R, value_2, &res); init_s21_decimal(&R); copy_bits(res, &R); set_bit_big(&Q, i, 1); } } if (scaleDiv > 0) { mul_10_big(result); } s21_big_decimal res; init_s21_decimal(&res); add_big(*result, Q, &res); copy_bits(res, result); if (!is_zero_big(R)) { init_s21_decimal(value_1); mul_10_big(&R); copy_bits(R, value_1); } } while (!is_zero_big(R) && scaleDiv < 28); set_scale_big(result, scaleDiv); for (int i = 0; i < 7; i++) { printf("%lX ", result->bits[i]); } printf("\n"); }
位操作辅助函数
int mul_10_big(s21_big_decimal *dec) { s21_big_decimal temp = *dec; for (int i = 0; i < SIZE_BIG_DECIMAL - 1; i++) { temp.bits[i] *= 10; } temp.scale++; int overflowed = 0; if (getoverflow(&temp)) { overflowed = 1; } else { *dec = temp; } return overflowed; } int div_10_big(s21_big_decimal *dec) { uint64_t remained = 0; for (int i = SIZE_BIG_DECIMAL - 2; i >= 0; i--) { dec->bits[i] += remained << 32; remained = dec->bits[i] % 10; dec->bits[i] /= 10; } dec->scale--; return remained; } int add_big(s21_big_decimal big_dec1, s21_big_decimal big_dec2, s21_big_decimal *result) { int res = 0; normalization_big(&big_dec1, &big_dec2); for (int i = 0; i < SIZE_BIG_DECIMAL - 1; i++) { result->bits[i] += big_dec1.bits[i] + big_dec2.bits[i]; getoverflow(result); } return res; }
内容的提问来源于stack exchange,提问作者laptop22
相关产品推荐
相关产品推荐

