4

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

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

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

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

4

4 回答 4

3

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

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

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

于 2013-10-16T09:03:49.020 回答
2

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

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

于 2013-10-16T10:15:44.597 回答
1

实际上,默认的 int 和 long 是如此模糊,并且依赖于编译器/平台,以至于我试图避免它们。使用 int 和 long:

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

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

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

于 2013-10-16T13:43:57.683 回答
0

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

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

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

  • 某些库函数有int *参数,例如 frexp。您需要提供一个 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 为 ,gcc/clang 会对此发出警告long

  • 在许多平台int32_t上很长(32 位长),即使int也是 32 位,这是不幸的(我认为它可以追溯到 Microsoft 需要在 16/32/64 上处理事情并决定 long 应该是 32永远位,反之亦然)。

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

于 2020-03-03T23:44:08.787 回答