【问题标题】:C++ Does converting long, short and all ints to uint32_t, int32_t and so forth help at all?C++ 将 long、short 和所有 int 转换为 uint32_t、int32_t 等是否有帮助?
【发布时间】:2013-10-24 07:26:33
【问题描述】:

我运行一个使用 C++ 编码的游戏服务器,还有一点 ASM 和 C。我看到有人更新了我运行的同一台服务器,在所有更新中,所有 int、unsigned、short 以及其他所有内容他都更改为 int32_t、uint32_t、uint64_t 等等。

将它们全部更改为上述内容有什么好处吗?假设我将所有 int 更改为 int32_t,将所有 unsigned int 更改为 uint32_t,当然还有其他所有可能更改的内容。

我试图阅读和理解是否有任何好处,但我根本没有理解它们的真正含义。所以是的,问题是:按照我刚才所说的做有什么好处吗?

我使用的编译器是Orwell Dev-C++

【问题讨论】:

  • int32_t 具有指定的大小和范围。 intlong 含糊不清。只指定了最小值,并且它们的大小是特定于实现的。
  • 它有利于可移植性和一般的健壮性,但如果您只是构建和定位代码已经工作的特定配置,则可能没有太大区别。
  • 服务器在 Windows 7 64 位系统上运行。因此,使其适用于多个平台并不重要。我只是希望以某种方式提高游戏和网络的性能等等。
  • 这不太可能产生任何性能差异,因为您可能只是为相同大小的类型使用不同的名称。当您的代码在 long 大小不同的 Windows 和 Linux 上编译并且您正在将它们读/写到二进制数据时,它确实会产生很大的不同。
  • 询问做出改变的人为什么这样做

标签: c++ function int


【解决方案1】:

普通类型,如intunsigned int,具有可变大小,具体取决于您运行的平台。但是,int32_tuint32_t 在任何具有 32 位整数类型的平台上都保证为 32 位。在没有的平台上,它不存在。 int 的大小可能会有所不同,通常为 32 或 64 位长。相同的规则适用于其他类型,例如 int64_t 是 64 位。

例如在网络编程中需要知道数据类型的大小,因为网络数据包在不同的平台之间以不同的默认整数大小发送,而数据包中存储的数据大小(如地址和端口号)是总是一样。 IPv4 地址总是 32 位长,并且应该使用保证是这个大小的数据类型来存储它。

在大多数只存储数字的程序中,您应该使用普通类型。这些的大小是当前平台上最有效的。

【讨论】:

  • 那么更新它们可以执行游戏联网吗?例如服务器-客户端之间的连接,只要这些东西在服务器上更新。
  • 不,但他们可能已经这样做了,以使其在 32 位和 64 位平台上都可以工作。也许他们的一些代码取决于整数的大小。此外,他们可能这样做是为了在 64 位平台上节省内存,如果操作正确,如果使用 32 位 insted 或 64 位,您可以将整数的内存使用量减少 50%。
  • @Pete,我可以补充一下,哪些平台没有?
  • @Atle - 当然,您必须在紧迫的期限内将代码移植到该平台。 <g>.
  • Int32_t 保证为 32 位,不一定是 4 字节。
【解决方案2】:

uint32_tint32_t 通过固定大小和符号为数据类型的处理添加更多控制 - 恕我直言,您在程序中的可预测性越高,它就越好。您还可以在 typename 上查看它是否未签名,这可能并不总是不言而喻的

通过明确定义的大小,您在编写可移植代码时也会受到更多保护。

【讨论】:

  • 不,对转化没有其他限制。 uint32_tint32_t 是对应的内置整数类型的 typedefs。他们确实施加的约束是,如果目标平台没有具有那些 精确 大小的整数类型,则 不存在
  • 是的,你当然是对的,我已经编辑了我的答案,感谢您的提醒。
  • [u]int32_t, [u]int16_t, [u]int8_t 将在不同的处理器之间具有共同的大小(在可能的情况下)。但这不是灵丹妙药:例如在`int16_t x = -1; uint16_t 阈值 = 3; ... if( x>thresh ) ` , x>thresh 在 16 位机器上为真(希望有编译器警告),在 int 为 32 位时为假。
【解决方案3】:

实际上,默认的 int 和 long 非常模糊,并且依赖于编译器/平台,因此我尝试避免使用它们。使用 int 和 long:

  • 如果您需要知道结构的大小,您需要知道每个体系结构、每个操作系统、每个编译器的 int 和 long 字节数。这是浪费宝贵的大脑。
  • 如果您需要向某人解释在该哈希表中发生冲突的可能性,您会说“这取决于 int 的大小,这取决于您的架构”,还是说 1.0e-5 ?换言之,int 和 long “取消定义”程序的属性。
  • 如果您使用 int,并且编译器发誓那是 64 位,则将其优化为 32 或 16 位的可能性很小。因此,如果您想要的只是代表一个短符号的空间,那么您最终会使用更多的内存......并不是说我知道许多带有 2^32 个字符的字母。

使用更多信息类型,如 uint32_t 或 uint_least32_t,您的编译器也许可以做出更好的假设并使用 64 位,如果它认为这会带来更好的性能。我不确定。但是作为人类,你有更好的机会理解你的程序运行良好的值范围。

此外,所有二进制协议都可能需要指定整数的大小和字节序。

【讨论】:

    【解决方案4】:

    在某些情况下我对int32_t 没有问题,例如结构字段,但是 将所有的int 写成int32_tunsigned 写成uint32_t(为了便携性?)的做法被过度使用了;我认为,实际上,您并没有从中获得任何真正的可移植性好处,而且还有一些明显的缺点。

    • 您正在编写的代码很可能只会在int 为32 位的机器上编译。如果您要将其移植到具有 16 位整数的机器上,那么您遇到的问题通常比一揽子 typedef 解决的问题要大得多。
    • 如果您确实迁移到 16 位机器,您可能希望将大量本地 int32_t 变量更改为 int,因为其中大部分是计数和索引,16 位机器不能有超过 32K 的大多数东西,但人们只是出于习惯写了它们,如果你把它们留为 int32_t 代码会很大而且很慢。
    • int 将来某个时候是 64 位?不会发生,原因有很多,其中大多数只是务实的事情。
    • 在一些奇怪的机器上int 可能是例如24 位。非常不寻常,但同样,你遇到的问题比 typedef 解决的问题更大,如果移植到这样一个野兽,你可能要做的第一件事就是更改所有 int32_t,它们只是将事情计算回 int .

    它不能解决可移植性问题。有什么缺点?

    • 某些库函数具有int * 参数,例如频率。您需要提供一个 int 变量的地址,否则它不会移植,并且 int32_t 可能是也可能不是 int,即使 int 是 32 位(见下文)。我见过有人写frexp( val, (int*)&myvar); 只是为了他们可以写int32_t myvar; 而不是int myvar;,这很糟糕,并且如果int32_t 的大小与int 不同,则会产生编译器无法检测到的错误。

    • 同样,printf( "%d", intvar); 需要一个 int,而不是一些恰好与 int 大小相同但可能真的很长的 typedef,如果 int32_t 是 long,gcc/clang 会发出警告。

    • 在许多平台上,int32_t 很长(32 位长),尽管 int 也是 32 位,但这是不幸的(我认为这可以追溯到微软需要重新处理16/32/64 并决定 long 应该永远是 32 位,反之亦然)。

    • 在跨不同平台移植代码时,不确定 int32_t 是 int 还是 long 可能会导致 c++ 重载问题。

    【讨论】:

      猜你喜欢
      • 2020-04-08
      • 1970-01-01
      • 2016-12-16
      • 2014-02-05
      • 1970-01-01
      • 2014-03-13
      • 2015-05-06
      • 2013-01-19
      • 2015-01-20
      相关资源
      最近更新 更多