使用uint8,uint16等

时间:2013-02-25 07:55:38

标签: c++ c memory-management embedded

目前我正在使用针对32位MIPS平台的代码库(C,C ++混合)。处理器是一个相当现代的处理器[只是提到我们有很好的处理能力和内存]。

代码库使用数据类型,如uint8 [1字节宽无符号整数],uint16 [2字节宽无符号整数],uint32 [4字节宽无符号整数]等。

我知道在将代码移植到不同平台时,这些构造的用法是如何有用的。

我的问题是:

  1. 使用uint16有什么用/有用,其中uint32也足够了(如果有的话)?

  2. 使用较短的数据类型(考虑数据对齐)是否可以节省内存使用量?

  3. 如果要节省几个字节的内存,在现代硬件中做些什么是明智的吗?

9 个答案:

答案 0 :(得分:23)

  

使用uint16有什么用/有益,uint32也足够了(如果有的话)?

如果那些uint16s是数组或结构的一部分,则可以节省内存,并且可能能够处理比那些相同数组或结构中的uint32s更大的数据集。这真的取决于你的代码。

数据协议和文件格式可能会使用uint16s,而使用uint32s可能不正确。这取决于格式和语义(例如,如果您需要将值从65535回绕到0,uint16将自动执行此操作,而uint32则不会。)

OTOH,如果那些uint16s只是单个局部或全局变量,用32位替换它们可能没有显着差异,因为它们可能由于对齐而占据相同的空间并且它们被传递为32无论如何,MIPS上的位参数(在堆栈或寄存器中)。

  

在使用较短的数据类型(考虑数据对齐)时,是否可以节省内存使用量?

可能会有节省,特别是当uint16s是许多结构或大数组元素的一部分时。

  

如果要保存几个字节的内存,在现代硬件中这样做是否明智?

是的,你降低了内存带宽(这总是一件好事),并且当你操作较少的数据时,你经常会降低各种缓存未命中(数据缓存和TLB)。

答案 1 :(得分:9)

首先,如果您定义了uint16等类型,它们在哪里定义?它们不是标准类型,因此将在某些专有标题中定义 - 可能是您的或可能由某些第三方库提供;在这种情况下,您必须问自己该代码的可移植性,以及您是否正在创建在其他应用程序中可能没有意义的依赖项。

另一个问题是许多库(不明智的IMO)使用各种名称定义这样的类型,例如UINT16,uint16,U16 UI16等,它变得有点像确保类型协议和避免名称冲突的噩梦。如果定义了 这样的名称,理想情况下应将它们放在命名空间中,或者给定一个特定于库的前缀,以指示它们被定义用于哪个库,例如rtos::uint16到{{1} }。

由于ISO C99标准库在stdint.h中提供了标准的位长特定类型,因此您应该优先使用它们在专有或第三方标头中定义的任何类型。这些类型具有rtos_uint16后缀,例如_t。在C ++中,它们可能被放置在uint16_t命名空间中(尽管这不是给定的,因为在C99中引入了标头)。

  

1]使用uint16有什么用/有用uint32也足够了(如果有的话)?

除了我之前建议偏好std::的{​​{1}}之外,至少有两个合理的理由使用长度特定类型:

  1. 匹配特定的硬件寄存器宽度。
  2. 在不同架构中强制实施通用且兼容的API。
  3.   

    2]在使用较短的数据类型(考虑数据对齐)时,是否可以节省内存使用量?

    可能,但如果记忆不是你的问题,那不是使用它们的好理由。值得考虑的可能是大型数据对象或数组,但全球应用很少值得努力。

      

    3]如果要保存几个字节的内存,在现代硬件中做些什么是合理的吗?

    见[2]。 “现代硬件”但并不一定意味着大量资源;例如,有大量的32位ARM Cortex-M器件,只有几Kb的RAM。这更多是关于模具空间,成本和功耗,而不是设计或建筑时代。

答案 2 :(得分:3)

cstdinttypedef个加载用于不同目的。

  • intN_t特定宽度
  • int_fastN_t表示最快的整数,至少有N位
  • int_leastN_t表示最小整数,至少有N位
  • 他们的unsigned当量

您应该根据自己的情况选择。在std::vector中存储数千并且没有进行大量计算? intN_t可能是你的男人。需要快速计算少量整数? int_fastN_t可能是你的家伙。

答案 3 :(得分:2)

答。 1.软件具有一定的要求和规范,严格说明在编码/解码或其他某些使用时仅占用参数的8/16位。因此,即使你将一个大于127的值分配到u8中,它也会自动为你修剪数据。

答。 2.我们不应该忘记我们的编译器超越智能来进行优化,无论是内存还是复杂性。因此,建议尽可能使用较小的内存。

答。 3.当然,在现代h / w中保存记忆是有意义的。

答案 4 :(得分:2)

必须检查生成的机器代码/汇编程序以验证是否有任何代码保存。在RISC类型架构中,典型的立即数是16位,但是使用uint16_t无论如何都会消耗一个完整的32位寄存器 - 因此,如果使用int类型,但是提交使用接近零的值将产生相同的结果并且更加可移植。

在现代平台中,IMO节省内存也是值得的。更严格的代码导致例如更好的电池寿命和更流畅的用户体验。但是,我建议只在使用(大型)数组时,或者当变量映射到某个真实的HW资源时,才能对大小进行微管理。

PS。编译器很聪明,但编写它们的人现在可以使它们变得更好。

答案 5 :(得分:1)

使用uint16_t代替uint32_t可以节省内存。它也可能是硬件约束(例如,某些外设控制器实际上发送的是16位!)但是,它可能不值得使用它,因为缓存和对齐考虑因素(你真的需要进行基准测试)。

答案 6 :(得分:1)

  

使用uint16有什么用/有益,uint32也足够了(如果有的话)?

有些unsigned char是16位值的CPU。如果不使用typedef,单元测试这样的代码会很困难(uint16只是适当类型的typedef)。

此外,通过使用这些typedef,可以更轻松地在不同平台上构建而不会出现太多问题。

  

在使用较短的数据类型(考虑数据对齐)时,是否可以节省内存使用量?

不,这不是重点。如果uint16unsigned short的typedef,那么您可以在任何地方使用unsigned short,但在不同的平台上可能会使用不同的类型。

当然,使用较小的类型会减少内存消耗。例如,使用uint16而不是uint32,但仅限于使用数组。

  

如果要保存几个字节的内存,在现代硬件中这样做是否明智?

这取决于平台:

  • 减少内存使用量意味着减少缓存未命中数
  • 如果支持,则有处理16位数据的SIMD功能

答案 7 :(得分:1)

您的问题的答案归结为一个关键概念:数据有多大?如果你正在处理很多,那么使用较小数据类型的好处是显而易见的。可以这样想:只需计算新发现的最大已知质数,就可以在典型的工作站上耗尽内存。这个数字本身需要超过一千兆字节才能存储。这并不包括计算实际数量。如果您使用的是厚数据类型而不是瘦数据类型,则可能需要使用两千兆字节。一个简单的例子,但仍然是一个好的例子。

答案 8 :(得分:1)

使用int32_t和朋友之类的精确宽度整数类型有助于避免intlong具有不同大小的平台之间的符号扩展错误。例如,当应用位掩码或位移时,这些可能发生。例如,如果您在long上执行这些操作,并且您的代码适用于32位long,那么对于64位long,它可能会中断。另一方面,如果您使用uint32_t,则无论平台如何,您都可以确切知道结果。

它们对于在平台之间交换二进制数据也很有用,您只需要担心存储数据的字节顺序而不是位宽;如果你在文件中写int64_t,你知道在另一个平台上你可以阅读它并将其存储到int64_t中。如果您在一个平台上写出long而不是64位,则最终可能需要在另一个平台上使用long long,因为long只有32位。

保存内存通常不是原因,除非您谈论的是非常有限的环境(嵌入式内容)或大型数据集(例如包含5000万个元素的数组)。