计算结构校验和时跳过/避免对齐填充字节

Eli*_*ron 4 c struct alignment

在计算C结构的校验和时,是否有通用的方法跳过/避免对齐填充字节?

我想通过对字节求和来计算结构的校验和。问题是,该结构具有对齐填充字节,它们可以获取随机(未指定)值,并使具有相同数据的两个结构获得不同的校验和值。

注意:我主要关注的是可维护性(无需更新代码即可添加/删除/修改字段)和可重用性,而不是可移植性(该平台非常具体且不太可能更改)。

目前,我找到了一些解决方案,但是它们都有缺点:

  1. 打包结构(例如#pragma pack (1))。 缺点:我宁愿避免打包以获得更好的性能。
  2. 逐字段计算校验和。缺点:修改结构时需要更新代码,并且需要更多代码(取决于字段数)。
  3. 在设置值之前,将所有结构字节设置为零。 缺点:我不能完全保证所有结构最初都为零。
  4. 安排结构字段以避免填充,并可能添加虚拟字段以填充填充。 缺点:不是通用的,修改结构时需要仔细重新排列结构。

有没有更好的通用方法?

计算校验和示例:

unsigned int calcCheckSum(MyStruct* myStruct)
{
    unsigned int checkSum = 0; 
    unsigned char* bytes = (unsigned char*)myStruct;
    unsigned int byteCount = sizeof(MyStruct);
    for(int i = 0; i < byteCount; i++)
    {
        checkSum += bytes[i];
    }
    return checkSum;
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*ger 7

在计算C结构的校验和时,是否有通用的方法跳过/避免对齐填充字节?

严格符合标准的程序没有这种机制。这是从

  1. 允许C实现出于任何原因或没有原因而在任何一个或多个成员之后使用任意填充对结构进行布局的事实,并且

  2. 事实

    当将值存储在结构或联合类型的对象中(包括在成员对象中)时,与任何填充字节对应的对象表示形式的字节将使用未指定的值。

    C2011,6.2.6.1/6

前者意味着标准没有提供保证结构布局不包含填充的一致方法,而后者则意味着从原则上讲,您无法做任何操作来控制填充字节的值-即使您最初将零填充为零,填充结构实例后,只要您分配给该对象或其任何成员,任何填充都将使用不确定的值。

实际上,您在问题中提到的任何方法都有可能在C实现和数据性质允许的范围内发挥作用。但是只有(2)可以逐个成员地计算校验和,才可以由严格遵循的程序使用,而且我所说的这个术语不是“通用的”。 这就是我会选择的。如果您有许多需要校验和的独特结构,那么可能值得部署代码生成器或宏魔术来帮助您进行维护。

另一方面,提供通用校验和的最可靠方法是行使特定于实现的扩展,该扩展使您能够避免包含任何填充的结构(您的(1))。请注意,这会将您与特定的C实现或兼容实现这种扩展的实现联系在一起,使其可能在某些系统上根本无法工作(例如,那些未对齐访问是硬错误的系统),并且可能会降低性能。其他系统。

您的(4)是避免填充的另一种方法,但这将是可移植性和维护的噩梦。尽管如此,它可以提供通用的校验和,从某种意义上说,校验和算法不需要关注单个成员。但也请注意,这也对类似于(3)的初始化行为提出了要求。那会便宜一些,但不会完全自动。

实际上,C实现并不一定要修改填充字节,但是也不一定要保留它们。特别是,即使您严格按照(3)进行零填充,也不能保证通过整个结构分配或当您按值传递或返回结构时都可以复制填充。如果要执行任何这些操作,则需要在接收端采取措施以确保零填充,并需要逐个成员注意。


R..*_*R.. 6

这听起来像是 XY 问题。为内存中的 C 对象计算校验和通常不是一个有意义的操作;结果取决于 C 实现(arch/ABI,如果甚至不是特定的编译器)并且 C 不承认容错编程模型能够处理由于内存的硬件故障而导致对象值从您身下改变的可能性-安全错误。校验和主要适用于磁盘上的序列化数据或通过网络传输的数据,您希望防止存储/传输中的数据损坏。并且 C 结构不用于序列化(尽管它们通常被滥用)。如果您编写了正确的序列化例程,那么您就可以对序列化的字节流进行校验和。

  • 这不一定是 XY 问题。在编写测试时,您可以存储预期的校验和值而不是整个预期的结构值。在测试代​​码中表达复杂结构的预期结构值(以及相等比较的代码)可能会很冗长、不切实际且难以维护,但表达预期的校验和要容易得多,因此有充分的理由计算校验和。如果我知道我的结构是字符数组、整数和枚举(例如没有指针)等简单事物的有效分层集合,那么就有充分的理由期望校验和有意义。 (2认同)