uint8_t 类型数组的元素是不是总是被打包到内存的连续字节中?

Posted

技术标签:

【中文标题】uint8_t 类型数组的元素是不是总是被打包到内存的连续字节中?【英文标题】:Will elements of an array of type uint8_t always be packed into consecutive bytes of memory?uint8_t 类型数组的元素是否总是被打包到内存的连续字节中? 【发布时间】:2019-10-21 13:36:42 【问题描述】:

我有一个用 C 语言编写的程序,它处理 24 位音频样本并将它们打包成 RTP 数据包以便通过网络传输。

我的代码将“样本”定义为 int32_t 和数组 uint8_t[4] 的联合,这样我就可以对整个样本执行算术运算,还可以访问其各个字节以打包到指定的 L24 编码方案中RFC3190。

这种方法在基于 ARM 和 Intel 的系统上运行良好,使用 gcc 编译。但是,我担心其他一些编译器或体系结构可能会填充 uint8_t 元素并因此破坏我的程序。这是一个有效的担忧吗?如果是这样,有没有更好的方法可以处理音频数据?

【问题讨论】:

不管填充,你肯定需要担心字节序。 是的,确实,能够访问样本的各个字节的部分好处是我能够以相反的顺序将它们写入 RTP 有效负载,从而从主机字节顺序转换到网络字节顺序,同时也丢弃未使用的字节。 【参考方案1】:

在 C 中静态声明的数组中,值存储在连续的内存位置(因此指针算法可用于迭代值)。联合的效果只会是两个成员从相同的内存位置开始,这可能是对齐的,也可能不是对齐的。可能会发生填充以获得这种对齐方式,但不会发生在特定数组的元素/值之间。

这里是关于填充和对齐的更多信息:

    http://c-faq.com/struct/padding.html http://c-faq.com/struct/align.html

【讨论】:

感谢您的链接。注意到下面 pmg 的响应(这解释了 [u]intN_t 类型没有任何固有的填充),即使系统具有字节可寻址内存,编译器是否仍有可能在 uint8_t 类型的元素之间添加填充? 不,它永远不会在具有字节可寻址内存的系统上的元素(数组的值)之间填充。如果发生这种“填充”,则系统不支持字节大小的值,它将恢复为 pmg 的答案,即“没有 uint8_t”。【参考方案2】:

虽然[u]intN_t 类型是可选的,但使用它们应该是安全的。 见C11 p7.20.1.1

    typedef 名称 uintN_t 指定宽度为 N 且无填充位的无符号整数类型。

如果你碰巧使用了一个实现没有uint8_t,它无论如何都不会编译。

【讨论】:

谢谢,我没有意识到 [u]intN_t 类型的规范声明没有填充位。

以上是关于uint8_t 类型数组的元素是不是总是被打包到内存的连续字节中?的主要内容,如果未能解决你的问题,请参考以下文章

uint8与uint8_t区别

在 uint8_t 数组中插入()

当我提取元素时,c#List 的数组是不是被移动?

用元素加载 std::queue<uint8_t*> 的更有效方法?

c++中uint8_t*值的含义和调试(打印)

java 值传递 数组传递