此代码是否合法/可移植?在struct外部访问数据 [英] Is this code legal/portable? Accesing data outside of struct

查看:118
本文介绍了此代码是否合法/可移植?在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆