在双精度数组上使用memset(,0,)是否合法?

And*_*rei 37 c standards

零数组的双精度数(使用memset(,0,))或含有双精度数的结构是否合法?

这个问题意味着两件事:

(1)从C标准的角度来看,这个UB不是吗?(在一个固定的平台上,这个UB怎么样......它只是浮动表示所有......)

(2)从实际角度来看:在intel平台上可以吗?(无论标准是什么).

Mat*_*lia 30

C99标准附件F说:

本附录规定了对IEC 60559浮点标准的 C语言支持.IEC 60559浮点标准特别适用于微处理器系统的二进制浮点算法,第二版(IEC 60559:1989),以前称为 IEC 559:1989IEEE二进制浮点运算标准(ANSI/IEEE 754-1985) ).用于与基数无关的浮点运算的IEEE标准(ANSI/IEEE 854-1987)概括了二进制标准以消除对基数和字长的依赖性.IEC 60559通常是指浮点标准,如IEC 60559操作,IEC 60559格式等.定义的实现__STDC_IEC_559__应符合本附录中的规范.如果指明了C语言与IEC 60559之间的绑定,则除非另有说明,否则IEC 60559指定的行为将被引用.

之后,

C浮动类型符合IEC 60559格式,如下所示:

  • float类型符合IEC 60559单一格式.
  • double类型符合IEC 60559双格式.

因此,如果IEC 60559基本上是IEEE 754-1985,并且它指定8个零字节意味着0.0(如@David Heffernan所说),这意味着如果您发现已 __STDC_IEC_559__定义,则可以安全地进行0.0初始化memset.

  • 实际上,正如我所理解的那样,它恰恰相反:它可能是任何东西,但如果你找到定义的`__STDC_IEC_559__`,你可以确定它是IEC 60559又名IEEE 754. (5认同)

Dav*_*nan 14

如果您正在谈论IEEE754,那么标准将+0.0定义为双精度为8个零字节.如果您知道自己受IEEE754浮点支持,那么这个定义很明确.

至于英特尔,我想不出在Intel x86/x64上不使用IEEE754的编译器.


Jen*_*edt 5

即使您不太可能遇到出现问题的机器,但如果您确实像问题标题中所示那样谈论数组并且如果这些数组在编译时的长度已知(即不是VLA),那么直接初始化它们可能会更方便

double A[133] = { 0 };
Run Code Online (Sandbox Code Playgroud)

应该总是有效。如果稍后您必须再次将这样的数组归零,并且您的编译器符合现代 C (C99),您可以使用复合文字来完成此操作

memcpy(A, (double const[133]){ 0 }, 133*sizeof(double));
Run Code Online (Sandbox Code Playgroud)

在任何现代编译器上,这应该与 一样高效memset,但具有不依赖于 的特定编码的优点double

  • 你确定它编译成相同的吗?我希望后者在堆栈上分配 133*8 个字节,将它们“memset”设置为 0(内联或通过调用),然后在简单的实现中调用“memcpy”。 (2认同)

Mat*_*ery 5

David Heffernan对你问题的第(2)部分给出了一个很好的答案.第(1)部分:

在一般情况下,C99标准不保证浮点值的表示.§6.2.6.1说:

除非本条款中另有说明,否则所有类型的陈述均未指明.

......而且该子条款没有进一步提及浮点数.

你说:

(在一个固定的平台上,这个UB怎么样......它只是浮动表示所有......)

确实 - " 未定义的行为"," 未指定的行为"和" 实现定义的行为" 之间存在差异:

  • " 未定义的行为"意味着任何事情都可能发生(包括运行时崩溃);
  • " 未指定的行为"意味着编译器可以以任何方式自由地实现某些合理的东西,但是不需要记录实现选择;
  • " 实现定义的行为"意味着编译器可以自由地以任何方式实现合理的东西,并且应该记录该选择(例如,请参阅此处了解最新版本的GCC记录的实现选择);

因此,由于浮点表示是未指定的行为,因此它可以从平台到平台以未记录的方式变化(其中"平台"在这里表示"硬件和编译器的组合"而不仅仅是"硬件").

(我不确定如何保证a double表示如此定义,即+0.0如果__STDC_IEC_559__定义了所有位零,如Matteo Italia的答案所述,实际上是在实践中.例如,GCC从未定义过这个,即使是使用许多硬件平台上的IEEE 754/IEC 60559.)