此代码是否合法/可移植?在struct外部访问数据 [英] Is this code legal/portable? Accesing data outside of struct
问题描述
根据评论和我对其他问题的回答,我发现了此代码。注释是根据5.3.4新[expr.new]允许访问结构外部,只要它被分配。但我没有找到说那个部分。
Based on a comment and answer on my other question I came out with this code. The comment was according to 5.3.4 New [expr.new] it is allowed to access outside of the struct as long as it is allocated. However I coudln't find the section that says that.
我想出了这个代码。我想知道它的便携式和完全定义和法律。输出是有趣的。 在gcc 中为10,10,12,而视觉工作室2010则显示为12,10,12。
I came up with this code. I wanted to know if its portable and completely defined and legal. The output is kind of interesting. in gcc it is 10,10,12 while visual studios 2010 shows 12,10,12.
在C ++ 11或C ++ 03中代码是否合法?我相信代码将在任何平台/ cpu与标准编译器对齐。
Is the code legal in C++11 or C++03? I believe the code will be align in any platform/cpu with a standard compiler.
-edit-如果你的惰性flex_struct是有问题的部分。 p>
-edit- In case your lazy flex_struct is the part that does questionable things.
#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);
}
推荐答案
使用此代码。
//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]
分配的东西,没有问题。如果你传递一个指向静态或自动数组的指针,那么对齐是一个问题。
Memory returned from new char[n]
is properly aligned for objects of the requested size or less. However, static and automatic char
arrays are not. So, if you always pass something allocated with new char[n]
here, there's no problem. If you pass a pointer to a static or automatic array, then alignment is a problem indeed.
struct struct_with_array : public STRUCT { TYPE buf[1]; };
索引超出数组边界是未定义的行为。只有 buf
的一个元素可以访问。请注意,原始答案中的代码不会出现此问题。
Indexing out of array bounds is undefined behaviour. There is only one element of buf
you can access. Note that this issue doesn't happen in the code in the original answer.
auto p = reinterpret_cast<struct_with_array*>(this);
我不完全确定这个转换的有效性,但我怀疑它破坏严格的别名。
I'm not entirely sure of the validity of this cast, but I suspect it breaks strict aliasing.
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 *)
)。
The C++ way would be std::vector<char>(1024);
, I guess. In any case sizeof(srcarray)
is likely not 1024, but probably 4 or 8 (equal to sizeof(char*)
).
auto v = MyVariableLengthStruct::head(srcarray);
从来没有一个 MyVariableLengthStruct
srcarray
指向的内存,因此这将只适用于POD类型。
There was never a MyVariableLengthStruct
constructed in the memory pointed by srcarray
, so this will only work for POD types.
这篇关于此代码是否合法/可移植?在struct外部访问数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!