简体   繁体   English

指向结构或类的指针与指向第一个字段的指针

[英]pointer to struct or class versus pointer to first field

I recently tried debugging a small program by printing the values of several pointers to the console. 我最近尝试通过打印指向控制台的多个指针的值来调试一个小程序。 The first was the memory address of a struct, and the others were the memory addresses of its fields. 第一个是结构的内存地址,其他是其字段的内存地址。 A stripped-down version of the code is as follows: 该代码的简化版本如下:

#include <iostream>

struct testingPointers
{
    int i;
    float f;
    double d;
} test;

int main()
{
   std::cout << &test << '\n' << &(test.i) << '\n' << 
            &(test.f) << '\n' << &(test.d);
}

And the output is: 输出为:

0x681110
0x681110
0x681114
0x681118

(obviously the exact values are different for different runs but they always have the same positions relative to each other). (显然,对于不同的运行,确切的值是不同的,但是它们始终相对于彼此具有相同的位置)。

I am confused because the value of first pointer--the memory location of test --is the same as that of the second one (the first field of test ). 我很困惑,因为第一指针的值-的存储器位置test --is相同第二个(的第一场的test )。 Does this mean that objects have no real unique memory address, and that a pointer to a struct or class simply points to its first field? 这是否意味着对象没有真正的唯一内存地址,并且指向结构或类的指针仅指向其第一个字段? If so, how do statements like 如果是这样,语句如何

a.b
a->b
a.b()

make sense if a is actually just its first field, and therefore does not have any fields or methods? 如果a实际上只是其第一个字段,因此没有任何字段或方法,是否有意义?

The address of an object shall always be the address of the first non-static member within that object. 对象的地址应始终是该对象内第一个非静态成员的地址。 Quoting from the standard (C++11-9.2-20): 引用标准(C ++ 11-9.2-20):

A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. 指向标准布局结构对象的指针(使用reinterpret_cast进行了适当的转换)指向其初始成员(如果该成员是位域,则指向其驻留的单元),反之亦然。 [ Note: There might therefore be unnamed padding within a standard-layout struct object, but not at its beginning, as necessary to achieve appropriate alignment. [注意:因此,在标准布局结构对象中可能会存在未命名的填充,但在其开始时可能没有,这是实现适当对齐所必需的。

The requirements for standard-layout are mentioned here: StandardLayoutType . 这里提到了标准布局的要求: StandardLayoutType

This can certainly be applied via nesting. 当然可以通过嵌套应用。 The standard makes no exceptions for the type of the first member except for bit-fields. 该标准位字段 ,对第一个成员的类型没有例外。 Ie: 即:

class X
{
public:
    int x;
};

class Y
{
public:
    X x;
    int y;
};

Y yobj;

By the standard, &yobj == &yobj.x == &yobj.xx . 按照标准, &yobj == &yobj.x == &yobj.xx

A class or struct just describes a collection of fields that should be kept together in memory, and have some semantic relationship between them and some operations that operate over them. 类或结构仅描述了字段的集合,这些字段应一起保存在内存中,并且在它们和对其进行操作的某些操作之间具有某种语义关系。 There is, in the simple case, nothing much more to the content of a class type object in memory than the members it is made up of (and some padding). 在简单的情况下,内存中类类型对象的内容只不过是由其组成的成员(和一些填充)所组成。 When you have a testingPointers object in memory, it is really just an int , a float and a double . 当内存中有一个testingPointers对象时,它实际上只是一个int ,一个float和一个double The concept of the class was only used to generate the correct executable code - it does not exist at run time (at least not for this purpose). 该类的概念仅用于生成正确的可执行代码-在运行时不存在(至少不是出于此目的)。

The important part from the standard regarding whether objects can share memory addresses is §1.8/6: 标准中关于对象是否可以共享内存地址的重要部分是第1.8 / 6节:

Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. 除非对象是大小为零的位域或基类子对象,否则该对象的地址为它占用的第一个字节的地址。 Two objects that are not bit-fields may have the same address if one is a subobject of the other, or if at least one is a base class subobject of zero size and they are of different types; 如果一个不是另一个的子对象,或者如果至少一个是零大小的基类子对象并且它们是不同类型,则两个不是位域的对象可能具有相同的地址; otherwise, they shall have distinct addresses. 否则,它们应具有不同的地址。

We can infer from this that because member test.i is a subobject of test , they may well have the same address. 由此可以推断,由于成员test.itest的子对象,因此它们可能具有相同的地址。

Once you look inside all of the objects of your program as deep as you can go, what you really have is a big collection of scalar values and adjacent bit-fields. 一旦尽可能深入地查看程序的所有对象,您真正拥有的就是标量值和相邻位域的大量集合。 These are known as memory locations in the standard. 这些在标准中称为存储位置 These are the things that really take up space. 这些是真正占用空间的东西。 The rest of your objects are all in some way composed of these. 您其余的对象都以某种方式由这些对象组成。

A memory location is either an object of scalar type or a maximal sequence of adjacent bit-fields all having non-zero width. 存储器位置是标量类型的对象,或者是全部具有非零宽度的相邻位字段的最大序列。 [ Note: Various features of the language, such as references and virtual functions, might involve additional memory locations that are not accessible to programs but are managed by the implementation. [ 注意:语言的各种功能(例如引用和虚函数)可能涉及程序无法访问但由实现管理的其他内存位置。 end note ] 尾注 ]

Just to clarify your confusions: 只是为了澄清您的困惑:

1).value of first pointer--the memory location of test--is the same as that of the second one (the first field of test). 1)。第一个指针的值-测试的存储器位置-与第二个指针的值相同(测试的第一个字段)。
Address of Struct and its first field got to be the same since struct is nothing both the collection of its fields contiguously. Struct的地址及其第一个字段必须相同,因为struct既不是其字段连续的集合。

在此处输入图片说明

You can also consider the case of arrays to further simplify the understanding, wherein the address of the array will obviously be equal to the first element (field) of the array. 您也可以考虑数组的情况,以进一步简化理解,其中数组的地址显然将等于数组的第一个元素(字段)。

2).Does this mean that objects have no real unique memory address, and that a pointer to a struct or class simply points to its first field? 2)。这是否意味着对象没有真正的唯一内存地址,并且指向结构或类的指针仅指向其第一个字段?
I think you are confusing it with that of JAVA wherein the Object is always allocated on Heap. 我认为您将其与JAVA混淆,其中对象始终分配在堆上。 In C++, struct/class is always allocated on Stack unless it's dynamic memory allocation (using 'new' operator) where the object is allocated in heap and a pointer variable (in Stack) will point to that object in heap. 在C ++中,结构/类始终分配在堆栈上,除非它是动态内存分配(使用'new'运算符),其中对象在堆中分配,并且指针变量(在堆栈中)将指向堆中的该对象。 Therefore, in the former case the struct variable will always have the same address as that of its first element (field). 因此,在前一种情况下,struct变量将始终与其第一个元素(字段)具有相同的地址。

Hope that helps. 希望能有所帮助。

A struct in memory consists of nothing more than its fields strung together. 内存中的结构仅由串在一起的字段组成。 There may be padding before the struct and/or between the fields, based on alignment needs, but there's not usually any extra "stuff" before the first field. 根据对齐需要,在结构之前和/或字段之间可能会有填充,但是在第一个字段之前通常没有任何多余的“填充”。 So the first field and the struct itself have the same address. 因此,第一个字段和结构本身具有相同的地址。

Remember that in C, types exist only at compile time. 请记住,在C语言中,类型仅在编译时存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM