Существует ли общий способ пропустить / избежать байтов заполнения выравнивания при вычислении контрольной суммы структуры C?
Не существует такого механизма, на который может опираться строго соответствующая программа.Это следует из
того факта, что реализациям C разрешено размещать структуры с произвольным заполнением после любого элемента или элементов по любой причине или без такового, а также
тот факт, что
Когда значение сохраняется в объекте структуры или типа объединения, в том числе в объекте-члене, байты представления объекта, которые соответствуют любым байтам заполнения, принимают неопределенноезначения.
( C2011, 6.2.6.1/6)
Первое означает, что стандарт не предоставляет соответствующего способа гарантиито, что структура структуры не содержит заполнения, и последнее означает, что в принципе вы ничего не можете сделать для управления значениями байтов заполнения - даже если вы изначально заполняете нулем экземпляр структуры, любой заполнитель принимает неопределенные значения, как толькопри назначении этому объекту или любому из его членов.
На практике вполне вероятно, что любой из подходов, которые вы упомянулиn в вопросе выполнит работу, в которой позволяет реализация C и характер данных.Но только (2), вычисляющий элемент контрольной суммы по элементу, может использоваться строго соответствующей программой, и эта программа не является «общей», как я понимаю, для обозначения этого термина. Это то, что я выбрал бы .Если у вас есть много различных структур, требующих контрольных сумм, то, возможно, стоит развернуть генератор кода или макрокоманду, чтобы помочь вам в поддержании вещей.
С другой стороны, ваш самый надежный способ обеспечить общее контрольное суммированиеэто реализовать расширение для конкретной реализации, которое позволяет вам избегать структур, содержащих любые дополнения (your (1)).Обратите внимание, что это свяжет вас с конкретной реализацией C или реализациями, которые реализуют такое расширение совместимо, что оно может вообще не работать в некоторых системах (например, в тех, где неправильный доступ является серьезной ошибкой), и что это может снизить производительность надругие системы.
Ваш (4) - альтернативный способ избежать заполнения, но это будет кошмар переносимости и обслуживания.Тем не менее, он может обеспечить общую контрольную сумму, в том смысле, что алгоритм контрольной суммы не должен будет уделять внимание отдельным членам.Но отметим также, что это также накладывает требование к поведению инициализации аналогично (3).Это будет дешевле, но не будет полностью автоматическим.
На практике реализации C не хотят произвольно изменять байты заполнения, но они также не всегда стараются сохранить их.В частности, даже если вы строго заполнены нулями, в соответствии с вашим (3), заполнение заполнением не гарантируется при присваивании всей структуры или при передаче или возврате структуры по значению.Если вы хотите сделать что-то из этого, вам нужно принять меры на принимающей стороне, чтобы обеспечить заполнение нулями, и требует внимания каждого члена.