我被分配了一个问题,其中某人可能放入任何类型的有符号/无符号整数,并且两个函数必须使用按位运算等返回相应的最小值和最大值 .
我正在尝试调整我对二进制补码的了解 - 范围由 - (2n-1)到(2n-1 - 1)定义为有符号,0到(2n - 1)为无符号值 .
但是,当我使用以下方法进行无符号时:
void create_minmax_unsigned() {
unknownun exponent = (sizeof(unknownun) * 8) - 1;
unknownun max = (1 << exponent) - 1;
printf("The max is %d", max);
}
并签署:
void create_minmax_signed() {
unknowns exponent = (sizeof(unknowns) * 8) - 1;
unknowns min = ((1 << exponent) + 1) - 1;
unknowns max = (1 << exponent) - 1;
}
这种方法适用于char(un / s),short(un / s),int(un / s),long(un / s)但不长,即64位 .
编辑:它实际上返回所有int类型的正确位数 . 但是,对于 long long
,它没有显示正确的范围 .
2 回答
long long
计算失败的原因是,分配的RHS计算为int
,并且您试图按int
的值过大 .这个spiel逐步发展答案 - 只有最终的代码才真正可行 . 早期版本有各种问题需要解决,一次只能解决一个问题 .
您需要将RHS强制转换为指定的类型:
返回多个值时遇到问题 . 使用
<inttypes.h>
和intmax_t
或uintmax_t
强制转换可以使您的打印代码更加强大:解决溢出问题
到目前为止,这使您的计算基本保持不变;它只是确保值的类型正确 . 但是,您的计算容易受到数字溢出的影响,这可能(非常)非常糟糕 - 它会导致带符号整数类型的未定义行为和无符号类型的错误答案 .
对于无法使用较大类型来覆盖罪孽的无符号类型,需要仔细创建2n-1,因为
2<sup>n</sup>
大于可以存储的值,因此它看起来像0.当你减去1时,你会得到正确的答案,但你真的不需要转移/取幂 .对于签名类型,您不能使用2n-1 - 1,因为无法表示2n-1 . 但是,您可以使用2 *(2n-2 - 1)1 . 负限制是减去一个值的否定值,导致:
未经测试的代码(错误):
经测试的代码(不是那么多错误):
汇编:
样品运行:
你不能只移动
1 << (sizeof(signed type)*CHAR_BIT-1)
,因为那是未定义的行为(如果sizeof(signed type) >= sizeof(int)
) . 那么(x+1)-1
是什么? (提示:x
,除非x
是INT_MAX,在这种情况下,'s undefined). So that doesn' t会得到一个负数,是吗?