【问题标题】:How can I maintainably determine sizeof(struct ...)s?如何可维护地确定 sizeof(struct ...)s?
【发布时间】:2013-04-10 06:18:03
【问题描述】:

假设我有一个结构:

struct myStruct
{
    int a;
    short b;
    char c;
};

在 Windows 中,MSDN states that int 占用 4 个字节,short 占用 2 个字节,char 占用 1 个字节。总共最多 7 个字节。

我了解大多数编译器会使用未指定的字节数填充结构以改善对齐。所以,当我执行这个程序时,

#include <stdio.h>

int main(void) {
    printf("%d\n", sizeof(struct myStruct));
    return 0;
}

我得到8 的输出。这意味着填充了 1 个字节。

有什么方法可以让我在代码中可维护地确定struct 的大小(缺少将单个sizeofs 相加)?

我问这个是因为以后,如果我需要更改我的结构以包含大约 15 个以上的元素,并且如果我再添加 5 个结构,我所有的 struct sizeofs 都会改变,导致事情变得混乱。

【问题讨论】:

  • 为什么需要结构的“逻辑”大小而不是实际大小?
  • 因为我正在处理套接字和根据结构大小计算要发送的字节的东西。所以在这里,实际的内存使用并不重要(除非我的内存用完了)。
  • 但在这种情况下,您需要 real 结构体大小。你有没有想过结构包装?
  • 不是真的,因为我并不总是发送整个结构。我知道使用真正的结构大小要容易得多,但不幸的是,我正在处理大量代码库(即使我想也无法更改)。是的,我读过关于 struct packing 的文章,但我不想尝试,因为我读过它会严重影响性能。
  • @AnishRam:为什么结构体的 sizeof 应该决定发送的字节数?您希望您的有线协议独立于编译主机的填充和字节序。因此,以可移植的方式将结构解压到字节缓冲区,然后发送。

标签: c struct sizeof maintainability


【解决方案1】:

你可以强制执行:

#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]

C_ASSERT(sizeof(struct myStruct) == 7); // or 8, whichever you want

只要大小偏离 7,代码就会停止编译。

您可以执行类似的操作来强制结构成员的偏移量。为此,您将需要 offsetof() 宏。

【讨论】:

  • 如何停止编译?该宏只能在运行时检查,对吗?我错过了什么吗?
  • @AnishRam 试试看。声明在编译时被解析。 extern char CAssertExtern[(expr)?1:-1] 是一个声明。如果它的元素计数为负,编译器将停止并出现相应的错误。
  • 附带说明,编译时断言的更好方法是 C 标准 static_assert,尽管只有全新的 C11 编译器支持它。请确保您的代码与未来的编译器兼容,将宏命名为 static_assert 而不是 C_ASSERT。
  • 天哪!你是对的。有用。这很漂亮。据我了解,如果该条件失败,编译器将尝试声明一个大小为 -1 的数组。对吗?
  • @AlexeyFrunze,只是好奇,你为什么要包含 extern 关键字?
【解决方案2】:

你可以试试pragma pack。它有助于保持对齐并具有许多灵活性。检查这个 http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index.jsp?topic=/com.ibm.xlcpp101.aix.doc/compiler_ref/pragma_pack.html

更新:刚刚看到你的评论,也许 pack 不是你的解决方案

【讨论】:

    猜你喜欢
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 2014-11-18
    • 2015-10-14
    • 2022-10-06
    • 2013-09-01
    相关资源
    最近更新 更多