【问题标题】:Is memset(&obj, 0, sizeof obj) less portable than initializing with {0}?memset(&obj, 0, sizeof obj) 的可移植性是否不如使用 {0} 初始化?
【发布时间】:2014-06-26 23:29:30
【问题描述】:

我最近遇到了 GCC 的错误,它阻止使用 {0} 初始化某些东西。 In that bug report,举报人说:

C标准库中的经典例子是mbstate_t:

mbstate_t state = { 0 }; /* correctly zero-initialized */

相对于普通但不便携:

mbstate_t state;
memset(&state, 0, sizeof state);

虽然我更喜欢并尝试使用{0} 将某些内容初始化为零,但我已经使用并且看到其他人使用memset 版本将某些内容设置为零。我过去没有遇到任何可移植性问题。

问题:在这里使用memset 真的不便携吗?如果是这样,在什么情况下它是不可移植的?

【问题讨论】:

  • iiuc,该错误不会防止使用={0} 初始化结构;它只是提出了一个不必要的警告,可以通过所有通常的方式来抑制。当然,这是一个错误,它被标记为已解决(仅在报告发布两年后 :))
  • @rici:是的,你是对的。我使用-Werror 构建,所以有时我会忘记什么是通常的错误和什么是通常的警告。

标签: c memset


【解决方案1】:

对于浮点和指针类型,不保证按位零为 (T)0。因此,如果您将其中一个 memset 设为零,那么您将得到最好的实现定义的东西。

This question 列出了一些空指针不是按位为零的机器。

我相信 Cray 做了一些机器示例,其中按位零不会使您的浮点数为零。

【讨论】:

  • memset 初始化适用于“float 和 double 类型,但前提是实现已定义宏 STDC_IEC_559 以声明它符合 IEC 60559 浮点算术附件”
  • 我并没有真正考虑 NULL 不为零的示例是有效的,因为标准要求 NULL 是“值为 0 的整数常量表达式,或者这样的表达式转换为输入void *"。
  • @Cornstalks:您误解了标准。该标准要求整数常量 0 在转换为指针类型时产生空指针。它不要求空指针由按位零表示。另见c-faq.com/null/machnon0.html
  • @YePhIcK 该宏可能不准确,请参阅我的评论here
【解决方案2】:

“为此目的使用 memset 假设全零位模式对应于零数值或空指针值。这对于大多数 C 实现中的大多数类型都是正确的,但不是ISO 标准的要求”。

以上引用摘自http://www.codepolice.org/c/memset.html(这是谷歌针对“memset 的可移植性问题”的第一个命中)

【讨论】:

    【解决方案3】:

    在这里使用memset 真的不便携吗?

    这取决于。

    如果是这样,在什么情况下它是不可移植的?

    使用memset 将整数设置为零位总是使整数为零。
    使用memset 将浮点数设置为零位通常会使数字为零,但这不能保证——这取决于浮点数的存储方式。 指针的故事也是一样的;位设置为零的指针不是NULL 指针。

    【讨论】:

    • 你知道mbstate_t 的便携方式是什么吗? C11 页。 7.29.6 (3) “[…] 零值 mbstate_t 对象可用于启动涉及任何多字节字符序列的转换,[…]”。我不确定,“零值”是什么意思。 This 说,{0} 是不太便携的方式,但这实际上是我认为“零值”的意思。
    猜你喜欢
    • 2022-01-07
    • 2012-12-12
    • 2015-09-01
    • 2019-10-19
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 2020-07-03
    相关资源
    最近更新 更多