我的印象是访问union除最后一个成员之外的成员是UB,但我似乎无法找到一个可靠的参考(除了声称它是UB但没有标准支持的答案).
那么,这是不确定的行为?
我一直在寻找,但找不到明确的答案.
很多人说使用工会来打字 - 双关语是不明确的和不好的做法.为什么是这样?考虑到你写入原始信息的内存并不仅仅是自己的改变,我看不出为什么它会做任何未定义的任何原因(除非它超出了堆栈的范围,但这不是一个联合问题,这将是糟糕的设计).
人们引用严格的别名规则,但在我看来,就像说你不能这样做,因为你做不到.
如果不打双关语,联盟的意义又是什么呢?我在某个地方看到它们应该被用来在不同的时间使用相同的内存位置来获取不同的信息,但为什么不在再次使用之前删除信息呢?
总结一下:
额外信息:我主要使用的是C++,但想了解它和C.特别是我正在使用工会在浮点数和原始十六进制之间进行转换以通过CAN总线发送.
我一直在std::memcpy用来规避严格的混叠很长一段时间.
例如,检查a float,像这样:
float f = ...;
uint32_t i;
static_assert(sizeof(f)==sizeof(i));
std::memcpy(&i, &f, sizeof(i));
// use i to extract f's sign, exponent & significand
Run Code Online (Sandbox Code Playgroud)
但是,这次,我检查了标准,我还没有找到任何可以验证这一点的东西.我所发现的是这个:
对于平凡可复制类型T的任何对象(可能重叠的子对象除外),无论对象是否保持类型T的有效值,组成对象的基础字节([intro.memory])都可以复制到char,unsigned char或std :: byte([cstddef.syn])数组.40如果将该数组的内容复制回对象,则该对象应随后保持其原始值.[例如:
Run Code Online (Sandbox Code Playgroud)#define N sizeof(T) char buf[N]; T obj; // obj initialized to its original value std::memcpy(buf, &obj, N); // between these two calls to std?::?memcpy, obj might be modified std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar …
c++ strict-aliasing undefined-behavior language-lawyer c++17
下面的代码通过一些位攻击执行快速反平方根操作.该算法可能是由Silicon Graphics在1990年代早期开发的,它也出现在Quake 3中. 更多信息
但是我从GCC C++编译器收到以下警告:解除引用类型惩罚指针将破坏严格别名规则
我应该使用static_cast,reinterpret_cast还是dynamic_cast在这种情况下使用?
float InverseSquareRoot(float x)
{
float xhalf = 0.5f*x;
int32_t i = *(int32_t*)&x;
i = 0x5f3759df - (i>>1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
return x;
}
Run Code Online (Sandbox Code Playgroud) c++ strict-aliasing gcc-warning undefined-behavior type-punning
既然isnan可以是宏(在C++ 98中)或在命名空间std中定义的函数(在C++ 11中),这个简单的例子说明了编写在两种情况下都有效的代码的明显(并且可能是天真的)方式.
#include <cmath>
int main() {
double x = 0;
using namespace std;
isnan(x);
}
Run Code Online (Sandbox Code Playgroud)
但是,编译它会在GCC(使用-std = c ++ 11)和Clang中产生错误:
test.cc: In function ‘int main()’:
test.cc:6:10: error: call of overloaded ‘isnan(double&)’ is ambiguous
isnan(x);
^
test.cc:6:10: note: candidates are:
In file included from /usr/include/features.h:374:0,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/os_defines.h:39,
from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h:426,
from /usr/include/c++/4.8/cmath:41,
from test.cc:1:
/usr/include/x86_64-linux-gnu/bits/mathcalls.h:234:1: note: int isnan(double)
__MATHDECL_1 (int,isnan,, (_Mdouble_ __value)) __attribute__ ((__const__));
^
In file included from test.cc:1:0:
/usr/include/c++/4.8/cmath:626:3: note: constexpr bool std::isnan(long double) …Run Code Online (Sandbox Code Playgroud) 以下是现代C中未定义的行为:
union foo
{
int i;
float f;
};
union foo bar;
bar.f = 1.0f;
printf("%08x\n", bar.i);
Run Code Online (Sandbox Code Playgroud)
并打印1.0f的十六进制表示.
但是以下是未定义的行为:
int x;
printf("%08x\n", x);
Run Code Online (Sandbox Code Playgroud)
那这个呢?
union xyzzy
{
char c;
int i;
};
union xyzzy plugh;
Run Code Online (Sandbox Code Playgroud)
这应该是未定义的行为,因为没有plugh编写成员.
printf("%08x\n", plugh.i);
Run Code Online (Sandbox Code Playgroud)
但是这个呢.这是未定义的行为吗?
plugh.c = 'A';
printf("%08x\n", plugh.i);
Run Code Online (Sandbox Code Playgroud)
现在大多数C编译器都有sizeof(char) < sizeof(int),sizeof(int)或者是2或4.这意味着在这些情况下,最多plugh.i会写入50%或25%,但读取剩余的字节将读取未初始化的数据,因此应该是未定义的行为.在此基础上,是整个读取未定义的行为?
我想用 gfortran 编译一个程序并-O3 -ffast-math启用它,因为它可以提供很好的性能提升。我很困惑,gfortranisnan()捕获了一些 NaN,但不是全部。看完之后
检查 C++ 中的 double(或 float)是否为 NaN
如何制作可移植的 isnan/isinf 函数
负 NaN 不是 NaN?
我的印象是,即使启用了快速数学,人们也可以通过位调整来检查 C 中的 NaN。然而,这让我感到困惑,因为快速数学
可能会导致依赖于数学函数的 IEEE 或 ISO 规则/规范的精确实现的程序输出不正确。
根据 gcc 4.7.2 的手册页。那么,如果数字没有按照 IEEE 标准表示,您如何知道要检查哪一位呢?如果您知道它,您将如何在 Fortran 95/03/08 中实现它?
不要费心发布(x \= x)依赖于 IEEE 规则的类似解决方案。他们给出的结果与 相同isnan()。我也知道-ffpe-trap=invalid,zero,overflow,但不想停止该程序。如果有帮助的话,我的操作系统是 64 位 LinuxMint 14。如果 Fortran 中不可能,防水的 C 解决方案也很好。
我正在尝试编写一个std::isnan()与 MSVC 2010 一起使用的程序。我包含cmath但不幸的是编译器返回错误:
isnan 不是 std 命名空间的一部分
MSVC 2010 是否支持 std(AKA C++11)中的此函数?
我正在用点和点之间的向量进行一些计算,对于我来说,当点非常接近时我得到了纳,这并不奇怪.我现在要做的是清除数组中存储在数组中的所有nan值以及良好的数据.我希望只使用一些代码:
if( angle[i] == nan ) { angle[i] = 0.0 };
Run Code Online (Sandbox Code Playgroud)
至少那是我尝试过的,当我尝试时我会遇到错误.有没有人知道如何摆脱nan值并用0.0替换它们?