首页 文章

C Non-Pod起始地址

提问于
浏览
1

在C中,struct的第一个元素与struct本身具有相同的地址 . 如果第一个元素是POD,对于C中的非POD结构是否同样如此?

例如,给定此代码:

struct bar
{
    struct bar *p1, *p2;
    unsigned char h;
}

struct foo
{
    struct bar node;
    int a;

    private:
        int x;
};

int main(void)
{
struct foo A;
struct bar *ptr;

ptr = &A.node;

struct foo *n = ((struct foo*)((char*)(ptr)-(unsigned long)(&((struct foo*)0)->node)));

return 0;
}

我得到“无效访问NULL对象的非静态数据成员'foo :: node'...可能错误地使用了offsetof”警告 .

我的问题是 - 我可以假设'node'位于foo(同一地址)的开头,即使这是一个非POD结构吗?

如果是,我可以使用重新解释演员,我没有得到警告:

struct foo *o = reinterpret_cast<struct foo*>(ptr);

那么,如果C结构以公共POD数据开始,那么第一个元素是否会按照标准共享对象的地址?

谢谢

--edit-- In a class with no virtual methods or superclass, is it safe to assume (address of first member variable) == this?被指出是一个可能的答案 . 它提到"Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allo- cated so that later members have higher addresses within a class object. "这并没有真正解决我的案例中的第一个元素是否与对象本身相同的地址 .

我认为既然标准没有说明什么,我不能认为是这样的 . 我可能需要将结构末尾的对象更改为指针,并根据需要处理它们 .

2 回答

  • 1

    标准在[class.mem] / 19中说

    如果标准布局类对象具有任何非静态数据成员,则其地址与其第一个非静态数据成员的地址相同 . 否则,其地址与其第一个基类子对象的地址(如果有)相同 . [注意:因此,在标准布局结构对象中可能存在未命名的填充,但不是在其开头,以实现适当的对齐 . - 尾注]

    因此,如果类是标准布局类,而您的标准布局类不是标准,则保证第一个成员的地址是类的地址 . 在你的情况下,它声明它是它的第一个基类的地址 . 由于您没有基础对象,这意味着第一个成员共享对象的地址,因为在对象的开头永远不会填充 . 这意味着 foo 的地址是 bar 成员的地址,因为 bar 是标准布局类,所以它也是 p1 的地址 .

    请注意,尝试在第一个成员之后获取任何成员是未定义的行为 . 类类型(包括 struct )允许在类的任何成员之间使用填充以进行对齐 . 这意味着您永远不知道其他成员与第一个成员的确切位置 .

  • -4

    根据Slava,因为虚拟表可以是struct的一部分所以简短的答案是否定的 . 现在vtable不是标准的一部分 . 它们只是实现虚拟事物并因此实现多态的机制 . 由于所有实际原因,答案仍然是否定的 .

    请参阅以下代码:

    #include <iostream>
    
    using namespace std;
    
    struct bar
    {
        struct bar *p1, *p2;
        unsigned char h;
    };
    
    struct foo
    {
        struct bar node;
        int a;
    
        private:
            int x;
    };
    
    int main(void)
    {
        struct foo A;
        struct bar *ptr;
    
        A.node.p1 = new bar();
        A.node.p2 = new bar();
        ptr = &A.node;
    
        struct foo *n = ((struct foo*)((char*)(ptr)-(unsigned long)(&((struct foo*)0)->node)));
        cout << n->a << endl;
    
        return 0;
    }
    

    代码使用 g++ -Wall -Werror -pedantic -std=c++14 test.cpp 编译 . 问题是我认为你没有为 p1p2 分配内存 .

相关问题