根据评论和answer on my other question我发布了此代码。注释是根据5.3.4 New [expr.new],只要它被分配,就允许在结构外部访问。但是,我找不到那个说那个的部分。
我想出了这段代码。我想知道它是否便携,完全定义和合法。输出很有意思。 in gcc它是10,10,12而2010年的视觉工作室显示为12,10,12。
C ++ 11或C ++ 03中的代码是否合法?我相信代码将在任何平台/ cpu中与标准编译器对齐。
-edit-如果你的懒惰flex_struct是做可疑事情的部分。
#include <iostream>
#include <new>
#include <cstring>
using namespace std;
template <typename STRUCT, typename TYPE> class flex_struct {
flex_struct(){}
public:
//should be safe to access and check what length the array is
static STRUCT* head(char*buff) {
//is this next line wrong?
//if((alignof(STRUCT)%reinterpret_cast<size_t>(buff))!=0) { throw std::exception(); }
return reinterpret_cast<STRUCT*>(buff);
}
struct struct_with_array : public STRUCT { TYPE buf[1]; };
TYPE* buff() {
//if(length==0) { throw std::exception(); }
auto p = reinterpret_cast<struct_with_array*>(this);
return p->buf;
}
};
typedef short testtype;
struct MyVariableLengthStruct : public flex_struct<MyVariableLengthStruct, testtype> {
int a, b;
char c;
};
struct MyVariableLengthStruct2 {
int a, b;
char c;
testtype buf[1];
};
struct MyVariableLengthStruct3a {
int a, b;
char c;
};
struct MyVariableLengthStruct3 : MyVariableLengthStruct3a {
testtype buf[1];
};
int main() {
auto srcarray=new char[1024];
//we don't actually need this line which is incorrect anyways (sizeof isnt 1024)
//memset(srcarray, 0, sizeof(srcarray)); //whats a C++ way to do this w/o writing a loop or function?
auto v = MyVariableLengthStruct::head(srcarray);
auto buff = v->buff();
auto dif1 = (int)buff-(int)v;
printf("%X %X %d\n", v, buff, dif1);
MyVariableLengthStruct2 v2;
auto dif2 = (int)v2.buf-(int)&v2;
printf("%X %X %d\n", &v2, v2.buf, dif2);
MyVariableLengthStruct3 v3;
auto dif3 = (int)v3.buf-(int)&v3;
printf("%X %X %d\n", &v3, v3.buf, dif3);
}
答案 0 :(得分:4)
我发现此代码存在很多问题。
//is this next line wrong?
//if((alignof(STRUCT)%reinterpret_cast<size_t>(buff))!=0) { throw std::exception(); }
return reinterpret_cast<STRUCT*>(buff);
从new char[n]
返回的内存与所请求大小或更小的对象正确对齐。但是,静态和自动char
数组不是。所以,如果你总是在这里传递用new char[n]
分配的东西,那就没问题了。如果将指针传递给静态或自动数组,那么对齐确实是一个问题。
struct struct_with_array : public STRUCT { TYPE buf[1]; };
从数组边界索引是未定义的行为。您只能访问buf
中的一个元素。请注意,原始答案中的代码中不会发生此问题。
auto p = reinterpret_cast<struct_with_array*>(this);
我不完全确定这个演员的有效性,但我怀疑它打破了严格的别名。
auto srcarray=new char[1024];
memset(srcarray, 0, sizeof(srcarray)); //whats a C++ way to do this w/o writing a loop or function?
我想,C ++的方式是std::vector<char>(1024);
。在任何情况下,sizeof(srcarray)
可能不是1024,但可能是4或8(等于sizeof(char*)
)。
auto v = MyVariableLengthStruct::head(srcarray);
在MyVariableLengthStruct
指向的内存中从未构造srcarray
,因此这仅适用于POD类型。