4.2.4.8
Structure type packing
In the CC-RH, the alignment of structure members can be specified at the C language level. This function is equivalent to the -Xpack option, however, the structure type packing directive can be used to specify the alignment value in any location in the C source.
Caution | The data area can be reduced by packing a structure type, but the program size increases and the execution speed is degraded. |
(1) | Format of structure type packing |
The structure type packing function is specified in the following format.
#pragma pack [(][1|2|4][)]
|
#pragma pack changes to an alignment value of the structure member upon the occurrence of this directive. The numeric value is called the packing value and the specifiable numeric values are 1, 2, 4. When the numeric value is not specified, the setting is the default alignment.Since this directive becomes valid upon occurrence, several directives can be described in the C source.
#pragma pack 1 /*structure member aligned using 1-byte alignment*/
struct TAG {
char c;
int i;
short s;
};
|
(2) | Rules of structure type packing |
The structure members are aligned in a form that satisfies the condition whereby members are aligned according to whichever is the smaller value: the structure type packing value or the member's alignment value.
For example, if the structure type packing value is 2 and member type is int type, the structure members are aligned in 2-byte alignment.
struct S {
char c; /*satisfies 1-byte alignment condition*/
int i; /*satisfies 4-byte alignment condition*/
};
#pragma pack 1
struct S1 {
char c; /*satisfies 1-byte alignment condition*/
int i; /*satisfies 1-byte alignment condition*/
};
#pragma pack 2
struct S2 {
char c; /*satisfies 1-byte alignment condition*/
int i; /*satisfies 2-byte alignment condition*/
};
struct S sobj; /*size of 8 bytes*/
struct S1 s1obj; /*size of 5 bytes*/
struct S2 s2obj; /*size of 6 bytes*/
|
A union is treated as subject to packing and is handled in the same manner as structure type packing.
union U {
char c;
int i;
};
#pragma pack 1
union U1 {
char c;
int i;
};
#pragma pack 2
union U2 {
char c;
int i;
};
union U uobj; /*size of 4 bytes*/
union U1 u1obj; /*size of 4 bytes*/
union U2 u2obj; /*size of 4 bytes*/
|
union U {
int i:7;
};
#pragma pack 1
union U1 {
int i:7;
};
#pragma pack 2
union U2 {
int i:7;
};
union U uobj; /*size of 4 bytes*/
union U1 u1obj; /*size of 1 byte*/
union U2 u2obj; /*size of 2 bytes*/
|
Data is allocated to the area of the bit field element as follows.
(a) | When the structure type packing value is equal to or larger than the alignment condition value of the member type |
Data is allocated in the same manner as when the structure type packing function is not used. That is, if the data is allocated consecutively and the resulting area exceeds the boundary that satisfies the alignment condition of the element type, data is allocated from the area satisfying the alignment condition.
(b) | When the structure type packing value is smaller than the alignment condition value of the element type |
- | If data is allocated consecutively and results in the number of bytes including the area becoming larger than the element type
The data is allocated in a form that satisfies the alignment condition of the structure type packing value. |
- | Other conditions
The data is allocated consecutively. |
struct S {
short a:7; /*0 to 6th bit*/
short b:7; /*7 to 13th bit*/
short c:7; /*16 to 22nd bit (aligned to 2-byte boundary)*/
short d:15; /*32 to 46th bit (aligned to 2-byte boundary)*/
} sobj;
#pragma pack 1
struct S1 {
short a:7; /*0 to 6th bit*/
short b:7; /*7 to 13th bit*/
short c:7; /*14 to 20th bit*/
short d:15; /*24 to 38th bit (aligned to byte boundary)*/
} s1obj;
|
(5) | Alignment condition of top structure object |
The alignment condition of the top structure object is the same as when the structure packing function is not used.
(6) | Size of structure objects |
Perform packing so that the size of structure objects becomes a multiple value of whichever is the smaller value: the structure alignment condition value or the structure packing value. The alignment condition of the top structure object is the same as when the structure packing function is not used.
struct S {
int i;
char c;
};
#pragma pack 1
struct S1 {
int i;
char c;
};
#pragma pack 2
struct S2 {
int i;
char c;
};
struct S sobj; /*size of 8 bytes*/
struct S1 s1obj; /*size of 5 bytes*/
struct S2 s2obj; /*size of 6 bytes*/
|
struct S {
int i;
char c;
};
struct T {
char c;
struct S s;
};
#pragma pack 1
struct S1 {
int i;
char c;
};
struct T1 {
char c;
struct S1 s1;
};
#pragma pack 2
struct S2 {
int i;
char c;
};
struct T2 {
char c;
struct S2 s2;
};
struct T tobj; /*size of 12 bytes*/
struct T1 t1obj; /*size of 6 bytes*/
struct T2 t2obj; /*size of 8 bytes*/
|
(7) | Size of structure array |
The size of the structure object array is a value that is the sum of the number of elements multiplied to the size of structure object.
struct S {
int i;
char c;
};
#pragma pack 1
struct S1 {
int i;
char c;
};
#pragma pack 2
struct S2 {
int i;
char c;
};
struct S sobj[2]; /*size of 16 bytes*/
struct S1 s1obj[2]; /*size of 10 bytes*/
struct S2 s2obj[2]; /*size of 12 bytes*/
|
For example, sobj.c, sobj.i, and cobj may be allocated consecutively without a gap in the following source program (the allocation order of sobj and cobj is not guaranteed).
#pragma pack 1
struct S {
char c;
int i;
} sobj;
char cobj;
|
(9) | Notes concerning structure packing function |
(a) | Specification of the -Xpack option and #pragma pack directive at the same time |
If the -Xpack option is specified when structure packing is specified with the #pragma pack directive in the C source, the specified option value is applied to all the structures until the first #pragma pack directive appears. After this, the value of the #pragma pack directive is applied.
If you subsequently write #pragma pack (no value), then the value specified with this option is applied following that line.
Example | When -Xpack=4 is specified |
struct S2 {...}; /*Packing value is specified as 4 in option.
-Xpack=4 option is valid: packing value is 4.*/
#pragma pack 2 /*Packing is specified as 2 in #pragma directive
struct S1 {...}; pragma pack(2) is valid: packing value is 2.*/
#pragma pack /*No specification of packing value with #pragma directive
struct S2_2 {...}; -Xpack=4 option is valid: packing value is 4.*/
|
(b) | Structure packing value and alignment value of members |
Structure members are arranged so that the alignment conditions match the smaller of the structure's packing value and the members' alignment value. For example, if the structure's packing value is 2, and a member type is long, then it is ordered to meet the 2-byte alignment condition.
struct S {
char c; /*Meets 1-byte alignment condition*/
long i; /*Meets 4-byte alignment condition*/
};
#pragma pack(1)
struct S1 {
char c; /*Meets 1-byte alignment condition*/
long i; /*Meets 1-byte alignment condition*/
};
#pragma pack(2)
struct S2 {
char c; /*Meets 1-byte alignment condition*/
long i; /*Meets 2-byte alignment condition*/
};
struct S sobj; /*Size 8 bytes*/
struct S1 s1obj; /*Size 5 bytes*/
struct S2 s2obj; /*Size 6 bytes*/
|
(c) | Nested #pragma pack specification |
Specify nested #pragma pack specifications for a structure as follows.
A warning is output for structure or union members with different alignment.
The alignment of members generating the warning will be in accordance with the #pragma pack statements in the source code.
#pragma pack 1
struct ST1
{
char c;
#pragma pack 4
struct ST4 //size=8, align=4 (Type is 4)
{
char c; //offset=1
short s; //offset=3
int i; //offset=5
} st4; //size=8, align=1 (1, because this is an ST1 member)
//Warning at location of member st4
int i;
} st1; //size=13, align=1
|
[Caution]
When pack=1 or #pragma pack 1 is specified for a structure, a union, or a class, its members cannot be accessed by using a pointer (including access using a pointer within a member function).
#pragma pack 1
struct st {
char x;
int y;
} ST;
int *p = &ST.y; /* The ST.y address may be an odd value. */
void func(void){
ST.y =1; /* Can be accessed correctly. */
*p = 1; /* Cannot be accessed correctly in some cases. */
}
|