c語言格式對齊填充
Prerequisite:
先決條件:
sizeof() operator in C/C++
C / C ++中的sizeof()運算符
Size of struct in C
C中的struct大小
We know that a struct size is not only the summation of all the data members, rather it's the minimum sum guaranteed. The compiler adds some padding for data member alignment.
我們知道,結構大小不僅是所有數據成員的總和,而且是保證的最小總和。 編譯器為數據成員對齊添加了一些填充。
In the C++ class, things are exactly the same as a struct. But there are a few more things.
在C ++類中,事物與結構完全相同。 但是還有更多的事情。
Firstly, while in C++ there are member functions, static data members. Do those have any contribution to the size of the class, objects?
首先,在C ++中有成員函數,即靜態數據成員。 這些對類,對象的大小有貢獻嗎?
The answer is no. Only the non-static data members contribute to the size of class and objects. This is because static members have only one instance which is shared among all objects. And normal member functions are like executable code which does not have size like data members.
答案是不。 只有非靜態數據成員才有助于類和對象的大小。 這是因為靜態成員只有一個實例,該實例在所有對象之間共享。 普通成員函數就像可執行代碼,沒有像數據成員那樣大小。
Like in the following class,
像下面的課一樣
class A {
private:
static int i;
int a;
char b;
public:
A()
{
a = 0;
b = '#';
}
A(int aa, char bb)
{
a = aa;
b = bb;
}
int get_int()
{
cout << a << endl;
return a;
}
char get_char()
{
cout << b << endl;
return b;
}
};
Size of the class should be sum of all the non-static data member+ padding, which is like below:
類的大小應為所有非靜態數據成員+填充的總和,如下所示:
Above is the alignment of class A and that's why the size of the class is 8 Bytes. Static data members and member functions have no contribution.
上面是A類的對齊方式,這就是為什么該類的大小為8 Bytes的原因 。 靜態數據成員和成員函數沒有貢獻。
編譯器如何添加填充? (How compiler adds padding?)
Now the question is how compiler adds padding and align? The method is compiler dependent and kind of greedy. It aligns till the boundary of maximum memory allocated.
現在的問題是編譯器如何添加填充和對齊? 該方法取決于編譯器并且有點貪婪。 對齊直到分配的最大內存邊界。
Here we find that max memory allocated is 8 Bytes, thus all the data members acquire 8 Bytes and the total size is 32 Bytes. Now the question is will it happen every time similarly?
在這里,我們發現分配的最大內存為8字節,因此所有數據成員都獲取8字節,總大小為32字節。 現在的問題是,是否每次都會同樣發生?
Is it like the number of data members * max datatype size?
就像數據成員數*最大數據類型大小一樣嗎?
The answer is no. It will try to align optimally keeping the same order. To check an example please follow the article on structure size in C. Also, later in this article, we have instances of such.
答案是不。 它將嘗試最佳對齊以保持相同順序。 要查看示例,請閱讀有關C語言中結構大小的文章。此外,在本文的稍后部分,我們將提供這樣的實例。
派生類的大小 (Size of a derived class)
What is the size of a derived class? Of course, a derived class has all data members of the base class it inherits and does it has its own copied of those data members too. Thus size should be the size of base class data members + size of derived class data members.
派生類的大小是多少? 當然,派生類具有其繼承的基類的所有數據成員,并且它也具有這些數據成員的自己的副本。 因此,大小應為基類數據成員的大小+派生類數據成員的大小。
Let's check the below code and the output.
讓我們檢查以下代碼和輸出。
In the above structure, we find that the size is 24 Bytes though the same data members have been used. This is due to the change in the order of the member declaration. In this case, the alignment and padding would be like below:
在上面的結構中,我們發現盡管使用了相同的數據成員,但大小為24字節。 這是由于成員聲明順序的更改。 在這種情況下,對齊方式和填充將如下所示:
#include <bits/stdc++.h>
using namespace std;
class Base {
protected:
static int i;
int a;
char b;
public:
Base()
{
a = 0;
b = '#';
}
Base(int aa, char bb)
{
a = aa;
b = bb;
}
int get_int()
{
cout << a << endl;
return a;
}
char get_char()
{
cout << b << endl;
return b;
}
};
class Derived : public Base {
private:
int c;
char d;
public:
Derived()
{
c = 0;
d = '#';
}
Derived(int cc, char dd)
{
c = cc;
d = dd;
}
int get_int()
{
cout << c << endl;
return c;
}
char get_char()
{
cout << d << endl;
return d;
}
};
int main()
{
Base b;
Derived d;
printf("Size of class Base: %lu\n", sizeof(Base));
printf("Size of object b: %lu\n", sizeof(b));
printf("Size of class Derived: %lu\n", sizeof(Derived));
printf("Size of object d: %lu\n", sizeof(d));
return 0;
}
Output:
輸出:
Size of class Base: 8
Size of object b: 8
Size of class Derived: 16
Size of object d: 16
So here the size of the base class object is 8 bytes, whereas the size of the derived class object is 16 Bytes.
因此,這里的基類對象的大小為8個字節,而派生類對象的大小為16個字節。
For the base class it's similar like below:
對于基類,它類似于以下內容:
While for the derived class it's like:
而對于派生類,它就像:
So the thing is the order of data members are being maintained. And since we know that the base class constructor is invoked first, that's why the base class members come first.
因此,關鍵是要維護數據成員的順序。 而且由于我們知道首先調用基類構造函數,所以這就是基類成員首先出現的原因。
Now let's change the order of data member in the derived class and check the size of the class & object.
現在,讓我們更改派生類中數據成員的順序,并檢查類和對象的大小。
#include <bits/stdc++.h>
using namespace std;
class Base {
protected:
static int i;
int a;
char b;
public:
Base()
{
a = 0;
b = '#';
}
Base(int aa, char bb)
{
a = aa;
b = bb;
}
int get_int()
{
cout << a << endl;
return a;
}
char get_char()
{
cout << b << endl;
return b;
}
};
class Derived : public Base {
private:
char d;
int c;
public:
Derived()
{
c = 0;
d = '#';
}
Derived(int cc, char dd)
{
c = cc;
d = dd;
}
int get_int()
{
cout << c << endl;
return c;
}
char get_char()
{
cout << d << endl;
return d;
}
};
int main()
{
Base b;
Derived d;
printf("Size of class Base: %lu\n", sizeof(Base));
printf("Size of object b: %lu\n", sizeof(b));
printf("Size of class Derived: %lu\n", sizeof(Derived));
printf("Size of object d: %lu\n", sizeof(d));
return 0;
}
Output:
輸出:
Size of class Base: 8
Size of object b: 8
Size of class Derived: 12
Size of object d: 12
Just changing the order of member we found that derived class is having size 12 Bytes now. So there must be some better alignment now.
只需更改成員的順序,我們發現派生類的大小現在為12個字節。 因此,現在必須進行更好的調整。
So, as we can think of compiler went for greedy alignment and now it's able to align optimally (Remember compiler can’t change the order of data member).
因此,正如我們可以想到的那樣,編譯器進行了貪婪對齊,現在它可以進行最佳對齊(記住編譯器無法更改數據成員的順序)。

Above is the alignment for the Derived class and now the size is 12 Bytes, instead of 16 because of the above alignment. We saw that compiler keeps aligning greedily & that's why it aligned char b of base class member & char d, which is its member, in the same row. When it tried to align int c, it could not as only 2 bytes were left. But instead of int, if it was char only then it would have aligned in the same line.
上面是Derived類的對齊方式,由于上面的對齊方式,現在的大小為12個字節,而不是16個字節。 我們看到編譯器保持貪婪地對齊,這就是為什么它在同一行中對齊基類成員的char b和其成員char d 。 當它嘗試對齊int c時 ,它不能,因為只剩下2個字節。 但不是INT,如果它是焦炭才把它會在同一線上。
虛擬關鍵字及其對大小的影響 (The virtual keyword and its effect on size)
We know in the derived class it can inherit the base class as virtual too. What would be the size of the derived class in that case? Will there be any changes?
我們知道,在派生類中,它也可以繼承虛擬類的基類。 在這種情況下,派生類的大小是多少? 會有變化嗎?
The answer is yes. There will be an additional 8 bytes which is nothing but the size of VTPR (Virtual Table pointer)
答案是肯定的。 將有一個額外的8個字節,不過就是VTPR(虛擬表指針)的大小
So, for the first derived class example, we got 16 Bytes, but here we have added the virtual keyword and got size 24 Bytes which is due to the size of VTPR.
因此,對于第一個派生類示例,我們獲得了16個字節,但是由于VTPR的大小,我們在這里添加了virtual關鍵字并獲得了24個字節的大小。
#include <bits/stdc++.h>
using namespace std;
class Base {
protected:
static int i;
int a;
char b;
public:
Base()
{
a = 0;
b = '#';
}
Base(int aa, char bb)
{
a = aa;
b = bb;
}
int get_int()
{
cout << a << endl;
return a;
}
char get_char()
{
cout << b << endl;
return b;
}
};
class Derived : virtual public Base {
private:
char d;
int c;
public:
Derived()
{
c = 0;
d = '#';
}
Derived(int cc, char dd)
{
c = cc;
d = dd;
}
int get_int()
{
cout << c << endl;
return c;
}
char get_char()
{
cout << d << endl;
return d;
}
};
int main()
{
Base b;
Derived d;
printf("Size of class Base: %lu\n", sizeof(Base));
printf("Size of object b: %lu\n", sizeof(b));
printf("Size of class Derived: %lu\n", sizeof(Derived));
printf("Size of object d: %lu\n", sizeof(d));
return 0;
}
Output:
輸出:
Size of class Base: 8
Size of object b: 8
Size of class Derived: 24
Size of object d: 24
So, here we got the idea of a normal class and object size. We learnt how the compiler aligns the data members and add padding. Also, we extended the discussion to the size of the derived class.
因此,這里我們有了一個普通的類和對象大小的想法。 我們了解了編譯器如何對齊數據成員并添加填充。 同樣,我們將討論擴展到派生類的大小。
To end the discussion let me just throw a brain teaser. What do you think would be the size of an empty class?
為了結束討論,我只想動腦子。 您認為空班級的人數多少?
Do you think it's 0?
你認為是0嗎?
#include <bits/stdc++.h>
using namespace std;
class A {
};
int main()
{
printf("Size of class A: %lu\n", sizeof(A));
return 0;
}
Output:
輸出:
Size of class A: 1
Well, the size of the empty class is not 0. This is actually to ensure that two different objects will have different addresses.
嗯,空類的大小不為0。這實際上是為了確保兩個不同的對象具有不同的地址。
翻譯自: https://www.includehelp.com/cpp-tutorial/size-of-a-class-in-cpp-padding-alignment-in-class-size-of-derived-class.aspx
c語言格式對齊填充