gpt4 book ai didi

c++ - 大小应该使用有符号整数还是无符号整数?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:07:17 25 4
gpt4 key购买 nike

标准库 vector::size()给出 size_t , 一个无符号数。在一次 CppCon 演讲中,我听到有人(是 Chandler Carruth 吗?)说这很不幸,应该使用有符号整数。

背景是没有为有符号整数定义溢出,因此编译器有更多的回旋余地。 Carruth 在一次谈话中展示了如何 uint8_t作为 for bzip2 中的循环索引在 x86 上创建的机器指令比 int8_t 多得多因为它必须使用掩码和移位显式模拟溢出。

在我现在处理的代码中,有一些严格为正的大小。这些表示为 size_t .这看起来不错,因为这表明它们不能为负。另一方面,不需要定义模运算,因此只要有符号整数足够大(我们达到 200),无符号整数就会为我们想要的算法提供错误的接口(interface)。

在代码中的某些点,存在从 0 到此大小的循环。然后减去循环索引并取绝对值。

当我用更现代的 GCC 7 编译它时,它无法解析 std::abs 的正确重载。因为size_t - size_t显然,给出了模棱两可的值(value)观。我已将代码更改为使用 int在循环索引中:

for (int t1 = 0; t1 < Lt; t1++) {
for (int t2 = 0; t2 < Lt; t2++) {

现在 abs(t1 - t2)工作得很好。但是比较t1 < Lt给出警告,因为它是有符号数和无符号数之间的比较。

什么是正确的方法?

  1. 对所有非负数使用无符号整数,然后使用 static_cast<int>()每当我需要做减法时。
  2. 对循环索引使用有符号整数,对容器大小使用无符号整数。然后使用 static_cast<int>在比较中。
  3. 到处都使用带符号的整数。当其他库返回无符号整数时,只需使用 static_cast<int>那里是为了满足警告。

最佳答案

“在一次演讲中,Carruth 展示了 uint8_t 作为 bzip2 中的 for 循环索引如何在 x86 上创建比 int8_t 更多的机器指令,因为它必须使用掩码和移位显式模拟溢出。”

好吧,如果您可以使用任何一种类型,则 for-range 必须限制为 [0, 127] .只需使用 int作为索引类型,那么。它根据定义是基本数学运算的自然类型,并且通常可以很好地映射到 CPU 寄存器。

使用为最小存储优化的类型不会生成最快的数学,不。这并不奇怪。您不能根据此类有缺陷的设置得出有关已签名与未签名的结论。

size_t - size_t 给出了不明确的值”

嗯,它不是,但它确实使用了模运算。 size_t(1)-size_t(2)==size_t(-1) ,但是 size_t(-1)是最大的可能值。这直接来自模块化数学的定义:x-1 < x , 除非 x-1环绕因为x==0 . (或等同于 x+1>x 时除外 x+1==0 )

调用 abs(size_t(x))因此也是毫无意义的,因为每个 size_t值为正。并将有符号整数与 size_t 进行比较同样充满意想不到的后果。显式转换是好的,因为它们使结果明确。

但是没有通用的解决方案来自动确定应该应用哪种类型转换。如果可以发明一条机械规则,我们可以将该规则留给编译器。我们没有,因为我们做不到。作为程序员,您必须从数字上考虑每种情况。

关于c++ - 大小应该使用有符号整数还是无符号整数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47283449/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com