当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?
我一直在使用isinf,isnan在Linux平台上运行完美的功能.但是这在OS-X上不起作用,所以我决定使用std::isinf std::isnan哪种适用于Linux和OS-X.
但英特尔编译器无法识别它,我猜它是英特尔编译器中的一个错误,根据http://software.intel.com/en-us/forums/showthread.php?t=64188
所以,现在我只是想避免麻烦和定义自己的isinf,isnan执行.
有谁知道如何做到这一点?
编辑:
我最终在我的源代码中进行了制作isinf/ isnan工作
#include <iostream>
#include <cmath>
#ifdef __INTEL_COMPILER
#include <mathimf.h>
#endif
int isnan_local(double x) {
#ifdef __INTEL_COMPILER
return isnan(x);
#else
return std::isnan(x);
#endif
}
int isinf_local(double x) {
#ifdef __INTEL_COMPILER
return isinf(x);
#else
return std::isinf(x);
#endif
}
int myChk(double a){
std::cerr<<"val is: "<<a <<"\t";
if(isnan_local(a))
std::cerr<<"program says isnan";
if(isinf_local(a))
std::cerr<<"program says isinf";
std::cerr<<"\n";
return 0;
}
int main(){
double a …Run Code Online (Sandbox Code Playgroud) 在一个特定的C++函数中,我碰巧有一个指向浮点缓冲区的指针,我想暂时用它来存储一半的双精度数.有没有一种方法可以使用此缓冲区作为临时空间来存储双打,这也是标准允许的(即,不是未定义的行为)?
总之,我想这样:
void f(float* buffer)
{
double* d = reinterpret_cast<double*>(buffer);
// make use of d
d[i] = 1.;
// done using d as scratch, start filling the buffer
buffer[j] = 1.;
}
Run Code Online (Sandbox Code Playgroud)
据我所知,没有简单的方法可以做到这一点:如果我理解正确,reinterpret_cast<double*>这样会因为类型别名而导致未定义的行为,并且memcpy在union不复制数据和分配额外空间的情况下无法使用浮点数/双数,这会失败在我的情况下,目的并且碰巧是昂贵的(并且在C++中不允许使用用于类型惩罚的联合).
可以假设浮动缓冲区已正确对齐以将其用于双精度.
下面的代码通过一些位攻击执行快速反平方根操作.该算法可能是由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
我的问题如下:
如果我想复制类类型,memcpy可以非常快速地完成.在某些情况下允许这样做.
我们有一些类型特征:
我想知道的是当类型是"可按位复制"时的确切要求.
我的结论是,如果两个is_trivally_copyable和is_standard_layout特征都为真,则类型是按位可复制的:
PS:当然,memcpy的结果必须正确.我知道我可以在任何情况下记忆,但不正确.
我们的项目中有一些严格类型的整数类型:
struct FooIdentifier {
int raw_id; // the only data member
// ... more shenanigans, but it stays a "trivial" type.
};
struct BarIdentifier {
int raw_id; // the only data member
// ... more shenanigans, but it stays a "trivial" type.
};
Run Code Online (Sandbox Code Playgroud)
基本上是这里提出的或类似于Unit Library 中使用的东西。
除了类型系统之外,这些结构基本上都是整数。
我的问题在这里现在是:有没有C ++语言保证这些类型奠定了相当于100%的内存作为一个经常int会是什么?
注意:由于我可以静态检查类型是否具有相同的大小(即没有填充),我真的只对无意外填充的情况感兴趣。我应该从一开始就添加这个注释
// Precodition. If platform would yield false here, I'm not interested in the result.
static_assert(sizeof(int) == sizeof(ID_t)); …Run Code Online (Sandbox Code Playgroud) 在回答另一个问题时,我想到了以下示例:
void *p;
unsigned x = 17;
assert(sizeof(void*) >= sizeof(unsigned));
*(unsigned*)&p = 17; // (1)
memcpy(&p, &x, sizeof(x)); // (2)
Run Code Online (Sandbox Code Playgroud)
第1行打破了别名规则.然而,第2行是好的.别名规则.问题是:为什么?编译器是否具有关于memcpy等函数的特殊内置知识,还是有一些其他规则可以使memcpy正常运行?有没有办法在标准C中实现类似memcpy的函数而不破坏别名规则?
我期待通过n3690,即将到来的选秀C++14标准,我在看节7.2段9:
如果两个枚举类型具有相同的基础类型,则它们是布局兼容的。
但是,我找不到任何说明枚举类型与其基础类型布局兼容的内容。对我来说,考虑到“基础类型”的含义,这应该遵循合理的语义,这似乎很明显,但标准是否真的保证了这一点?
sizeof(double) char在寻找将s 组合到 a 的方法时double,我读了几篇文章,std::memcpy推荐使用以下方法:
char bytes[sizeof(double)];
// fill array
double d;
std::memcpy(&d, bytes, sizeof(double));
Run Code Online (Sandbox Code Playgroud)
但是,我想知道为什么进一步使用d可以定义行为。
如果它不是一个double,而是一个复杂的类对象,那么访问它肯定也不会被定义,不是吗?那么,为什么double.
编辑:为了使我的问题清楚,我想指定我的目标:我想找到一种方法将多个chars 组合成 adouble并进一步使用这个 double,而不会导致未定义的行为。我不double希望指定 的值。无论如何,我认为这是不可能的,因为标准甚至没有说明任何有关大小的信息,更不用说double. 但是,我要求d有一些有效的(即“可访问的”)double值。
c++ ×8
c ×3
type-punning ×3
c++11 ×1
c++14 ×1
enums ×1
function ×1
gcc-warning ×1
math ×1
memory ×1