这段代码合法/便携吗?访问struct之外的数据

时间:2012-03-06 13:29:25

标签: c++ c++11

根据评论和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);
}

1 个答案:

答案 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类型。