Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C/C+中的对象/结构对齐+;_C++_G++ - Fatal编程技术网

C++ C/C+中的对象/结构对齐+;

C++ C/C+中的对象/结构对齐+;,c++,g++,C++,G++,为什么最后两行产生不同的值?我的指针运算有问题吗 size of an int: 4 size of a double: 8 size of test: 24 start address of the object: 0x7fffb9fd44e0 address of i member: 0x7fffb9fd44e0 start address of the double field: 0x7fffb9fd44e8 calculate the offset of the double field

为什么最后两行产生不同的值?我的指针运算有问题吗

size of an int: 4
size of a double: 8
size of test: 24
start address of the object: 0x7fffb9fd44e0
address of i member: 0x7fffb9fd44e0
start address of the double field: 0x7fffb9fd44e8
calculate the offset of the double field: 0x7fffb9fd45a0

因为最大的数据类型是8字节,所以结构会在int周围添加填充,或者将最大的数据类型放在第一位,或者将填充放在末尾!希望这有帮助

首先,您的代码是错误的,您希望在
h
之前添加字段的大小(即
int
),没有理由假定
是双的。其次,您需要首先将所有内容规范化为
char*
(指针算术是以指向的对象为单位完成的)

更一般地说,您不能依赖这样的代码来工作。编译器可以自由地在字段之间插入填充,以便将内容与单词边界对齐,等等。如果您确实想知道特定字段的偏移量,可以使用
offsetof
宏。它在C++中的<代码> <代码>中定义,在C++中<>代码> <代码> > < /p> 大多数编译器都提供了一个选项来删除所有填充(例如,GCC的
\uuuuu属性\((打包))


我相信只有在POD类型上使用
offsetof
才是定义明确的。

这与:

(&te + sizeof(double))
你应该做:

&((&te)[sizeof(double)])

&te+sizeof(double)
相当于
&te+8
,相当于
&(&te)[8])
。也就是说,由于
&te
具有类型
test*
&te+8
增加了
test
大小的八倍,因此编译器可以自由地将
struct
隔开,但它们希望通过第一个成员,并且通常使用填充来对齐单词边界以提高速度

请参见以下内容:


等。

你是对的——问题在于指针算法。

添加到指针时,指针的增量为该指针类型的倍数

因此,
&te+1
将是
&te
之后的24个字节


您的代码
&te+sizeof(double)
将添加
24*sizeof(double)
或192个字节。

使用
offsetof()
宏可以更清楚地看到发生了什么:

(char*)(&te) + sizeof(int)
在另一个系统(SPARC)上,我得到:

编译器将在结构成员之间插入填充字节,以确保每个成员正确对齐。如您所见,对齐要求因系统而异;在一个系统(x86)上,
double
为8字节,但只需要4字节对齐;在另一个系统(SPARC)上,
double
为8字节,但需要8字节对齐

也可以在结构的末尾添加填充,以确保在拥有结构类型的数组时所有内容都正确对齐。例如,在SPARC上,编译会在结构的末尾添加4个字节的填充



该语言保证第一个声明的成员的偏移量为0,并且成员按声明顺序排列。(至少对于简单的结构来说是这样的:C++元数据可能使事情复杂化)

<代码>(& Te+sieZof(double))< /> >应该是代码>(& Te+SieZoof(int))< /> >(或者在您想要偏移之前的所有元素的大小);我认为每个字段将填充8这个对象,正如测试的总大小为24所示。@windfinder:为什么?是64位操作系统吗?是64位。我想每个字段应该是8个字节,因为最大字段的大小是8,我没有指示编译器打包它。你说的“byte*”是什么意思?在C++中,这不是一个有效的关键字,所以我假设是速记。可以使用<代码>无符号char */COD>或<代码> SIZEZT 。请记住,关于对齐的评论也是正确的,您不能真正依赖于此行为。这真的有效吗?这不就是让你向前走sizeof(char*)*sizeof(int)字节吗?它应该向前走
sizeof(char)*sizeof(int)
bytes。和
sizeof(char)
应该是1。这是可行的,但它是sizeof(double),而不是int的大小。一个恼人的事情是,当您将它设置为char*(并尝试将其传递给std::out)时,它会打印一个空行。我刚刚将它转换回一个测试*:(test*)((char*)(&te)+sizeof(double)))我看到当您试图使用未对齐成员的地址时,使用
\uu属性(packed))
的代码会爆炸。@KeithThompson:我希望编译器不会愚蠢到生成失败的代码。如果平台不支持未对齐的访问,我希望编译器要么(a)编译失败,要么(b)以冗长的方式进行访问…@windfinder:但正如我所指出的,类代码基本上是不可依赖的,所以这并不重要…@OliCharlesworth:我也希望如此,但我很失望。看见问题是,一旦您获取未对齐成员的地址,编译器就无法知道它未对齐。@windfinder:它并不不准确;没有理由假设编译器使用的是
sizeof(double)
作为对齐方式……对,Drew也是这么说的。那么正确的语法是什么?谢谢@windfinder:嗯,你已经看到
&te.h
给出了你想要的答案。还是你在寻找不同的东西?对不起,我不太清楚你想做什么-/只是在玩序列化/反序列化。试着看看如果我可以访问一个空格*,或者类似的东西,我将如何计算字段的位置。不完全是他们想要的。第一个成员总是在偏移0,成员总是按声明的顺序排列(至少对于C,C++,对于POD类型)。换个说法,或者不用担心。按照逻辑顺序声明成员可能值得付出额外的填充代价——特别是因为填充在不同的系统中会有所不同。在我的编译器中,我看不到这种重新排列。是否存在触发此问题的特定编译器/设置?科伦
&((&te)[sizeof(double)])
(char*)(&te) + sizeof(int)
#include <iostream>
#include <cstddef>

using namespace std;

struct test
{
    int i;
    double h;
    int j;
};

int main()
{
    test te;
    te.i = 5;
    te.h = 6.5;
    te.j = 10;

    cout << "size of an int:   " << sizeof(int)    << endl; // Should be 4
    cout << "size of a double: " << sizeof(double) << endl; // Should be 8
    cout << "size of test:     " << sizeof(test)   << endl; // Should be 24 (word size of 8 for double)

    cout << "i: size = " << sizeof te.i << ", offset = " << offsetof(test, i) << endl;
    cout << "h: size = " << sizeof te.h << ", offset = " << offsetof(test, h) << endl;
    cout << "j: size = " << sizeof te.j << ", offset = " << offsetof(test, j) << endl;

    return 0;
}
size of an int:   4
size of a double: 8
size of test:     16
i: size = 4, offset = 0
h: size = 8, offset = 4
j: size = 4, offset = 12
size of an int:   4
size of a double: 8
size of test:     24
i: size = 4, offset = 0
h: size = 8, offset = 8
j: size = 4, offset = 16