Per aggiungere a ciò che altri hanno già detto:
Se si desidera esaminare, è possibile utilizzare l'opzione compilatore o programma esterno per l'uscita del struct disposizione.
Considerate questo file:
// test.cpp
#include <cstdint>
class Test_1 {
int64_t first : 40;
int64_t second : 24;
};
class Test_2 {
int64_t first : 40;
int32_t second : 24;
};
// Dummy instances to force Clang to output layout.
Test_1 t1;
Test_2 t2;
Se usiamo una bandiera uscita di layout, come ad esempio Visual Studio /d1reportSingleClassLayoutX
(dove X
è tutto o parte del nome della classe o struct) o Clang ++ s '-Xclang -fdump-record-layouts
(dove -Xclang
racconta la compilatore per interpretare -fdump-record-layouts
come comando di frontend di Clang invece di un comando di frontend GCC), possiamo scaricare i layout di memoria di Test_1
e Test_2
sullo standard output. [Purtroppo, non sono sicuro di come fare questo direttamente con GCC.]
Se lo facciamo, il compilatore di uscita i seguenti layout:
cl /c /d1reportSingleClassLayoutTest test.cpp
// Output:
tst.cpp
class Test_1 size(8):
+---
0. | first (bitstart=0,nbits=40)
0. | second (bitstart=40,nbits=24)
+---
class Test_2 size(16):
+---
0. | first (bitstart=0,nbits=40)
8. | second (bitstart=0,nbits=24)
| <alignment member> (size=4)
+---
clang++ -c -std=c++11 -Xclang -fdump-record-layouts test.cpp
// Output:
*** Dumping AST Record Layout
0 | class Test_1
0 | int64_t first
5 | int64_t second
| [sizeof=8, dsize=8, align=8
| nvsize=8, nvalign=8]
*** Dumping IRgen Record Layout
Record: CXXRecordDecl 0x344dfa8 <source_file.cpp:3:1, line:6:1> line:3:7 referenced class Test_1 definition
|-CXXRecordDecl 0x344e0c0 <col:1, col:7> col:7 implicit class Test_1
|-FieldDecl 0x344e1a0 <line:4:2, col:19> col:10 first 'int64_t':'long'
| `-IntegerLiteral 0x344e170 <col:19> 'int' 40
|-FieldDecl 0x344e218 <line:5:2, col:19> col:10 second 'int64_t':'long'
| `-IntegerLiteral 0x344e1e8 <col:19> 'int' 24
|-CXXConstructorDecl 0x3490d88 <line:3:7> col:7 implicit used Test_1 'void (void) noexcept' inline
| `-CompoundStmt 0x34912b0 <col:7>
|-CXXConstructorDecl 0x3490ee8 <col:7> col:7 implicit constexpr Test_1 'void (const class Test_1 &)' inline noexcept-unevaluated 0x3490ee8
| `-ParmVarDecl 0x3491030 <col:7> col:7 'const class Test_1 &'
`-CXXConstructorDecl 0x34910c8 <col:7> col:7 implicit constexpr Test_1 'void (class Test_1 &&)' inline noexcept-unevaluated 0x34910c8
`-ParmVarDecl 0x3491210 <col:7> col:7 'class Test_1 &&'
Layout: <CGRecordLayout
LLVMType:%class.Test_1 = type { i64 }
NonVirtualBaseLLVMType:%class.Test_1 = type { i64 }
IsZeroInitializable:1
BitFields:[
<CGBitFieldInfo Offset:0 Size:40 IsSigned:1 StorageSize:64 StorageOffset:0>
<CGBitFieldInfo Offset:40 Size:24 IsSigned:1 StorageSize:64 StorageOffset:0>
]>
*** Dumping AST Record Layout
0 | class Test_2
0 | int64_t first
5 | int32_t second
| [sizeof=8, dsize=8, align=8
| nvsize=8, nvalign=8]
*** Dumping IRgen Record Layout
Record: CXXRecordDecl 0x344e260 <source_file.cpp:8:1, line:11:1> line:8:7 referenced class Test_2 definition
|-CXXRecordDecl 0x344e370 <col:1, col:7> col:7 implicit class Test_2
|-FieldDecl 0x3490bd0 <line:9:2, col:19> col:10 first 'int64_t':'long'
| `-IntegerLiteral 0x344e400 <col:19> 'int' 40
|-FieldDecl 0x3490c70 <line:10:2, col:19> col:10 second 'int32_t':'int'
| `-IntegerLiteral 0x3490c40 <col:19> 'int' 24
|-CXXConstructorDecl 0x3491438 <line:8:7> col:7 implicit used Test_2 'void (void) noexcept' inline
| `-CompoundStmt 0x34918f8 <col:7>
|-CXXConstructorDecl 0x3491568 <col:7> col:7 implicit constexpr Test_2 'void (const class Test_2 &)' inline noexcept-unevaluated 0x3491568
| `-ParmVarDecl 0x34916b0 <col:7> col:7 'const class Test_2 &'
`-CXXConstructorDecl 0x3491748 <col:7> col:7 implicit constexpr Test_2 'void (class Test_2 &&)' inline noexcept-unevaluated 0x3491748
`-ParmVarDecl 0x3491890 <col:7> col:7 'class Test_2 &&'
Layout: <CGRecordLayout
LLVMType:%class.Test_2 = type { i64 }
NonVirtualBaseLLVMType:%class.Test_2 = type { i64 }
IsZeroInitializable:1
BitFields:[
<CGBitFieldInfo Offset:0 Size:40 IsSigned:1 StorageSize:64 StorageOffset:0>
<CGBitFieldInfo Offset:40 Size:24 IsSigned:1 StorageSize:64 StorageOffset:0>
]>
Si noti che la versione di Clang I utilizzata per generare questa uscita (quella utilizzata da Rextester) sembra di default per ottimizzare entrambi i bitfield in una singola variabile, e non sono sicuro di come disabilitare questo comportamento.
** La dimensione ** aumenta, non l'allineamento. Nel primo caso, il primo e il secondo fanno parte dello stesso int64_t. Nel secondo caso, ovviamente non possono. –
Cerca di ottenere indirizzi di campi, o anche meglio - assemblaggio di codice generato da un post che accede a entrambi i campi. O almeno - quale compilatore usi? – lorond
@lorond GCC 5.3.0 – xinaiz