【问题标题】:Is it guaranteed that memset will zero out the padding bits in a structure?是否保证 memset 会将结构中的填充位清零?
【发布时间】:2012-01-22 21:40:34
【问题描述】:

一般来说,根据 C 标准,是否保证带有 0 的 memset() 将 C 结构中的填充位清零?

gcc 呢?

例如,类似:

struct MyStruct
{
    unsigned char   member1;
    unsigned int    member2;
    char        member3;
    unsigned char   member4;
    float       member5;    
};

struct MyStruct ms;

memset(&ms, 0, sizeof( struct MyStruct));

【问题讨论】:

  • 你能给我们看一个代码示例吗?
  • 我不明白是什么让你怀疑。
  • 那么简短的回答:是的。它会将ms 占用的整个内存区域归零。填充位和所有...
  • @MK,我在某处看到了一条评论“即使您在使用它们之前已经对这些结构进行了 memset,也不要 memcmp 结构”。我的想法是,如果填充位已经 memset 为 0,那么以后使用 memcmp 不会有任何问题。可能是我发现的参考是错误的。
  • 我认为这可能是一个好主意,通常不要依赖 memcmp 来比较你的结构,因为如果你忘记在哪里忘记 memset,你手上就会有一个很难找到的错误。因此,除非已经证明它是性能瓶颈,否则请编写显式比较函数。还可以想象这样一种情况,您有一个 char buf[20],在一个结构中设置为“aaa”,在另一个结构中设置为“bbb”,然后将两者都设置为“c”。现在这些结构在逻辑上是相等的,但 memcmp 会认为它们是不同的。

标签: c gcc memset


【解决方案1】:

也许值得注意的是,memset 对您的结构(或数组,或基元,或任何您碰巧释放它的内存块)一无所知,所以即使它想留下填充位完好无损,它甚至不知道它们在哪里。

【讨论】:

  • 这不是真的;所有最近的编译器都知道memset 的语义并围绕它进行优化,而且编译器当然确实知道填充在哪里。
【解决方案2】:

是的,memset 将 32 位值写入从给定地址开始的给定长度的连续内存区域。在您的情况下,memset 使用(32 位值)0 写入区域。

所以如果你做一个长度为sizeof (your_struct)memset,你应该没问题:

memset(&ms, 0, sizeof(struct MyStruct));

【讨论】:

    【解决方案3】:

    如果这很重要,您可能会做一些不安全且不可移植的事情。

    是的,memset 调用会将任何填充位(或字节)设置为 0——但语言中不能保证将 float 对象设置为全位为零会将其设置为 0.0。这同样适用于指针:不保证所有位为零是空指针。 (在这两种情况下,大多数实现都是如此。)

    最初的 ISO C90 或 C99 标准甚至不保证所有位为零是整数类型的 0 的有效表示; C99 之后的技术勘误之一添加了这样的保证(仅适用于整数类型)。

    为了可移植性,如果您希望某个值为零,请明确设置它。您还可以对静态对象和初始化器中的省略成员利用零值初始化。

    一个术语的挑剔:“填充位”是整数类型表示的一部分(通常都没有)。 struct 成员之间的填充是填充 bytes

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-22
      • 2016-10-05
      • 2011-01-01
      • 2017-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多