在C99标准告诉我们:
结构对象内可能有未命名的填充,但不是在其开头。
和
在结构或联合的末尾可能有未命名的填充。
我假设这也适用于任何 C++ 标准,但我没有检查它们。
让我们假设在 ARM Cortex-M 上运行的 C/C++ 应用程序(即在应用程序中使用两种语言)将一些持久数据存储在本地介质(例如串行 NOR 闪存芯片)上,并在上电后读取它循环,可能在将来升级应用程序本身之后。升级后的应用程序可能是用升级后的编译器(我们假设是 gcc)编译的。
让我们进一步假设开发人员很懒惰(当然不是我),并且直接将一些普通的 C 或 C++ 流式传输struct到闪存,而不是像任何偏执的有经验的开发人员那样首先将它们序列化。
事实上,有问题的开发人员很懒惰,但并非完全无知,因为他阅读了AAPCS(Arm 架构的过程调用标准)。
除了懒惰之外,他的理由如下:
structs 以避免在应用程序的其余部分出现未对齐问题。offsetof和 total sizeof)完全struct由 AAPCS为任何 C 或 C++ 确定。不过,开发者是有良心的,他有点担心:
我的问题是:那个懒惰的开发人员的生活有多危险?换句话说,struct在上述假设下,填充在 C/C++ 中的稳定性如何?
在提出这个问题两周后,收到的唯一答案并没有真正回答所提出的问题。我也在ARM 社区论坛上问过完全相同的问题,但根本没有答案。
然而,我选择接受3246135作为答案,因为:
我将没有正确答案视为与此案非常相关的信息。软件问题解决方案的正确性应该是显而易见的。在我的问题中所做的假设可能是正确的,但我无法轻易证明。此外,如果假设不正确,在一般情况下,后果可能是灾难性的。
相比风险,开发者在使用答案中暴露的策略时的负担似乎非常合理。假设一个恒定的字节序(这很容易强制执行),它是 100% …
In [4]: df = pd.DataFrame({'a': [True, False, True], 'b': [False, False, False],
...: 'c': [False, False, False], 'd': [False, True, False],
...: 'e': [False, False, False]})
In [5]: df
Out[5]:
a b c d e
0 True False False False False
1 False False False True False
2 True False False False False
In [6]: df[df.any()[df.any()].index]
Out[6]:
a d
0 True False
1 False True
2 True False
Run Code Online (Sandbox Code Playgroud)
[6] 下的代码做了我想要的。然而,我的问题是:有更好的解决方案吗?也就是说,更简洁和/或更优雅。