About __align (n)

Source: Internet
Author: User
Tags modifier

"Go": http://www.cnblogs.com/ye-moooooo/p/4601189.html

__align

The __align keyword instructs the compiler to align variables on n-byte boundaries.

__align is a storage class modifier. It does not affect the type of the function. Grammar

<code class= "literal" >__align (<em class= "replaceable" ><code>n</code></em>) </ Code>

Where: N

is the alignment boundary.

For local variables, the n value can be 1, 2, 4, or 8.

For global variables, n can have any value with a maximum of 2 0x80000000 power.

The __align keyword is placed immediately before the variable name. usage

It is useful to declare a variable with a regular alignment boundary less than N,__align (n). Eight-byte alignment can significantly improve the performance of VFP instruction.

You can use __align with extern and static. Limit

Because __align is a storage class modifier, it cannot be used for:

types, including typedef and struct definitions

function arguments.

Only alignment can be made. That is, you can align two-byte objects to 4 bytes, and you cannot align 4-byte objects by two bytes. Sample

__align (8) Char buffer[128]; Buffer starts on Eight-byte boundary
void foo (void)
{
...
__align int i; This alignment value isn't permitted for
//a local variable ...
}

__align int i; Permitted as a global variable.

--------------------------------------------------------------------------------------------------------------- --------------------------------------

--------------------------------------------------------------------------------------------------------------- --------------------------------------

One. What is byte alignment, why should I align it?
    Modern computer memory space is divided by byte, theoretically it seems that access to any type of variable can start at any address, but the reality is that when accessing a particular type of variable, it is often accessed at a particular memory address. This requires that all types of data be arranged in space according to certain rules, rather than in order of one after another, which is alignment.
The role and cause of     alignment: There is a great deal of difference in storage space for each hardware platform. Some platforms have access to certain types of data only from certain addresses. For example, some of the architecture of the CPU to access a variable does not have to be aligned, when the error occurs, then programming in this architecture must ensure byte alignment. Other platforms may not, but the most common is the loss of access efficiency if the data is not aligned according to its platform requirements. For example, some platforms start every time from the even address, if an int (assuming 32-bit system) if stored in the beginning of the even address, then a read cycle can read out the 32bit, and if the location of the beginning of the odd address, it will take 2 reading cycles, The 32bit data can be obtained by piecing together the high and low byte of the results of two readings. Obviously, the reading efficiency is much lower.

Two. The effect of byte alignment on the program:
    Let's take a look at a few examples (32bit,x86 environment, GCC compiler):
set struct body as follows:
struct A
{
     int A;
    Char b;
    short C;
};
struct b
{
    char b;
    int A;
    short C;
};
The length of the various data types on the 32-bit machine is now known to be as follows:
Char:1 (signed unsigned)    
Short:2 (signed unsigned)    
Int:4 (Signed and unsigned)    
Long:4 (signed unsigned)    
float:4    double:8
What about the size of the top two structures?
The result is:
sizeof (Strcut A) has a value of 8
sizeof (struct B) is one

The structure body A contains a 4-byte length int, a 1-byte length char and a 2-byte length of the short data one, and B is the same; the a,b size should be 7 bytes.
The result of this is because the compiler wants to align data members in space. This is the result of aligning the compiler's default settings, so we can change the compiler's default alignment settings, of course. For example:
#pragma pack (2)//* Specify 2-byte alignment */
struct C
{
Char b;
int A;
Short C;
};
#pragma pack ()/* To cancel the specified alignment and restore the default alignment */
The value of sizeof (struct C) is 8.
The modified alignment value is 1:
#pragma pack (1)//* Specify 1-byte alignment */
struct D
{
Char b;
int A;
Short C;
};
#pragma pack ()/* To cancel the specified alignment and restore the default alignment */
The sizeof (struct D) value is 7.
We'll explain the role of the #pragma pack () later.

Three. What principle does the compiler align with?
Let's first look at four important basic concepts:
1. The alignment value of the data type itself:
For char data, its own alignment value is 1, for the short type 2, for the int,float,double type, its own alignment value is 4, Unit bytes.
2. A struct or a class's own alignment value: The value of its member's own alignment value.
3. Specify alignment Value: Value value of the specified alignment when #pragma pack (value).
4. Valid alignment values for data members, structs, and classes: their own alignment values and the value of the specified alignment value.
With these values, we can easily discuss the members of the specific data structures and their own alignment. Valid alignment value n is the final value used to determine how the data is stored in the address, most importantly. A valid alignment of n means "Snap to n", which means that the data "holds the starting address%n=0". Data variables in the structure are emitted in the order defined. The starting address of the first data variable is the starting address of the structure. The member variables of the structure should be aligned to emit, and the structure itself should be aligned according to its own valid value round (that is, the total length of the struct member variable should be an integral multiple of the effective alignment value of the structure, combined with the following example). This will not be able to understand the values of the above examples.
Example Analysis:
analysis example B;
struct B
{
Char b;
int A;
Short C;
};
Let's say B starts emitting from the address space 0x0000. The specified alignment value is not defined in this example, which defaults to 4 in the author environment. The self alignment value of the first member variable B is 1, is smaller than the specified or specified alignment value of 4, so its valid alignment value is 1, so its address 0x0000 conforms to 0x0000%1=0. The second member variable A, its own alignment value is 4, so the valid alignment value is 4, Therefore, it can only be stored in the four contiguous byte spaces from the starting address 0x0004 to the 0x0007, and the 0x0004%4=0 is reviewed, and immediately after the first variable. The third variable, C, has its own alignment value of 2, so the valid alignment value is also 2, which can be stored in the two-byte space 0x0008 to 0x0009, in line with 0x0008%2=0. So everything from 0x0000 to 0x0009 is stored in B content. Then look at the data structure B's own alignment value for its variable maximum alignment value (here is B) so that is 4, so the effective alignment of the structure is also 4. According to the requirements of the structural body rounding, 0x0009 to 0x0000=10 Byte, (10+2)%4=0. So the 0x0000a to the 0x000b is also occupied by the structural body B. So B from 0x0000 to 0x000b a total of 12 bytes, sizeof (struct b) = 12; Actually, if this is the one, it's already aligned to the byte, because its starting address is 0, so it's definitely aligned, and then 2 bytes are added, is because the compiler to achieve the access efficiency of the structure array, imagine if we define a structure B array, then the first structure start address is 0 no problem, but the second structure? All elements of an array are next to each other, as defined by the array, and if we do not add the size of the structure to the integer multiple of 4, Then the starting address for the next structure will be 0x0000a, this obviously does not satisfy the address alignment of the structure, so we are going to add the structure to the integer multiple of the valid alignment size. In fact, such as: for char data, its own alignment value is 1, for the short type is 2, for Int,float, Double with its own alignment value of 4, these existing types of their own alignment values are also based on the array, only because the lengths of these types are known, so their own alignment values are known.
Similarly, analyze the above example C:
#pragma pack (2)//* Specify 2-byte alignment */
struct C
{
Char b;
int A;
Short C;
};
#pragma pack ()/* To cancel the specified alignment and restore the default alignment */
The first variable B has its own alignment value of 1, specifies that the alignment value is 2, so that its valid alignment value is 1, assuming C starts from 0x0000, then B is stored in 0x0000, conforms to 0x0000%1= 0, the second variable, its own alignment value is 4, the specified alignment value is 2, so the valid alignment value is 2, So the order is stored in 0x0002, 0x0003, 0x0004, 0x0005 four consecutive bytes, in line with the 0x0002%2=0. The third variable C has its own alignment value of 2, so the valid alignment value is 2, in order to store
In 0x0006, 0x0007, in line with 0x0006%2=0. So from 0x0000 to 0x00007 a total of eight bytes is stored in C variables. and C's own alignment value is 4, so C's valid alignment value is 2. Also 8%2=0,c occupies only eight bytes of 0x0000 to 0x0007. So sizeof (struct C) =8.

Four. How do I modify the compiler's default alignment values?
1. In the VC IDE, you can modify this: [project]| The struct member alignment of the Code generation option category the Settings],c/c++ tab is modified by 8 bytes.
2. When encoding, you can modify this dynamically: #pragma pack. Note: It's pragma, not progma.

Five. For byte alignment, how do we consider in programming?

If you want to consider saving space in programming, then we only need to assume that the first address of the structure is 0, and then each variable according to the principle of the above arrangement can be, the basic principle is to the structure of variables in accordance with the type size of small to large declarations, Minimize the filling space in the middle. Another is to space in exchange for the efficiency of time, we are shown to fill the space to align, for example: there is a use of space-time approach is to explicitly insert reserved members:
struct a{
Char A;
Char reserved[3];//use space to swap time
int b;
}

Reserved members have no meaning to our program, it just fills up the space to achieve the purpose of byte alignment, of course, even without this member usually the compiler will give us automatic filling alignment, we add it to only play an explicit role in the reminder.

Six. Byte alignment may pose a potential risk:
Many of the pitfalls of alignment in your code are implicit. For example, when you force type conversions. For example:
unsigned int i = 0x12345678;
unsigned char *p=null;
unsigned short *p1=null;

p=&i;
*p=0x00;
p1= (unsigned short *) (p+1);
*p1=0x0000;
The last two codes, which access unsignedshort variables from odd-numbered boundaries, clearly do not conform to the rules of alignment.
On x86, similar operations only affect efficiency, but on MIPS or SPARC, it may be an error because they require byte alignment.

Seven. How to find the problem with byte alignment:
If an alignment or assignment problem occurs first view
1. Compiler's big little end setting
2. See if the system itself supports non aligned access
3. If the support to see the alignment is set or not, if you do not see the access needs to add some special decorations to flag its special access operations.

Eight. Alignment processing under Arm

From Dui0067d_ads1_2_complib

3.13 Type Qulifiers

Partially excerpted from arm compiler document alignment Section

Snap To use:
1.__align
   This modifies the byte bounds of the highest-level object. When using LDRD or STRD in the assembly,
   will use this command __align (8) for cosmetic restrictions. To ensure that the data Objects are aligned accordingly.
   This decorated object commands a maximum of 8 byte limits, allowing 2-byte objects to be 4-byte
   aligned, but not 4-byte objects 2 bytes aligned. The
   __align is a storage class modification that modifies only the top-level type objects that cannot be used in structs or function objects.
  
2.__packed
__packed is a byte-aligned
1. You cannot align packed objects
2. All objects have access to both read and write without Access
3. float and a structure that contains float and an object that is not __packed will not be aligned
4.__packed has no effect on local shape variables
5. Forcing the conversion of a unpacked object to a packed object is undefined, and the shaping pointer can be legally determined
Righteousness is packed.
     __packed int* p;//__packed int does not make sense
6. Alignment or non-aligned read-write access issues
__packed struct struct_test< br> {
char A;
int b;
char c;
};   //define the following structure the starting address of B must be misaligned
&NBSP;&NBSP;&NBSP;&NBSP;&N bsp;   //There may be a problem accessing B on the stack because the data on the stack is definitely aligned access [from CL]
//define the following variable as global static not on the stack
static char* p;
Static struct Struct_test A;
void Main ()
{
__packed int* Q;//This is defined as __packed to decorate the access below which the current Q points to the misaligned data address can

p = (char*) &a;
Q = (int*) (p+1);

*q = 0x87654321;
/*
The assembly instructions to get the assignment are clear.
LDR r5,0x20001590; = #0x12345678
[0xe1a00005] mov r0,r5
[0xeb0000b0] BL __rt_uwrite4//Here invoke a write 4byte operation function

[0xe5c10000] Strb r0,[r1, #0]//function perform 4 STRB operations and then return to ensure proper data access
[0xe1a02420] mov r2,r0,lsr #8
[0xe5c12001] Strb r2,[r1, #1]
[0xe1a02820] mov r2,r0,lsr #16
[0xe5c12002] Strb r2,[r1, #2]
[0XE1A02C20] mov r2,r0,lsr #24
[0xe5c12003] Strb r2,[r1, #3]
[0xe1a0f00e] mov pc,r14
*/

/*
If q is not __packed decorated then the assembler instruction is so direct that it will cause access to the odd address to fail
[0xe59f2018] Ldr r2,0x20001594; = #0x87654321
[0xe5812000] str r2,[r1, #0]
*/

This makes it clear how misaligned access can produce errors.
And how to eliminate the problem of non-aligned access
You can also see that the instruction difference between misaligned access and alignment access results in an efficiency problem
}

Nine. The consequences of an misaligned access to the border under arm
From http://blog.csdn.net/alenwelkin/archive/2006/12/19/1448324.aspx


You have written a program that defines a char array as follows:
Char p[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};

The long and short pointers are respectively used to point to the position of the p+3, which is 0x10963 after compilation, and is clearly an address that is not aligned to long and short.
The output of the program is as follows, the parentheses are the contents, the front is the address.
/mnt $./test
L 0x10963 (0x30201040), S 0x10963 (0x5040), Lt 0x30201040, St 0x5040

Disassembly of the executable file using the Arm-linux-objdump tool found that for a reference to a short pointer, the compiler did special processing to ensure that its reference was correct, while the long pointer did not do so.

unsigned long *l = (p + 3);
83e0:e59f3084 LDR R3, [PC, #132]; 846c <.text+0x190>
83e4:e50b3010 STR R3, [FP, #-16]
unsigned short *s = (p + 3);
83E8:E59F307C LDR R3, [PC, #124]; 846c <.text+0x190>
83ec:e50b3014 STR R3, [FP, #-20]
unsigned long lt = *l;
83f0:e51b3010 LDR R3, [FP, #-16]//variable L-&GT;R3
83f4:e5933000 LDR R3, [R3]//l content-&GT;R3
83f8:e50b3018 STR R3, [FP, #-24]//r3->lt
unsigned short st = *s;
83fc:e51b3014 LDR R3, [FP, #-20]//variable S-&GT;R3
8400:e5d32000 LDRB R2, [R3]//s content (low)->r2
8404:e5d33001 LDRB R3, [R3, #1]//s content (high)-&GT;R3
8408:e1823403 Orr R3, R2, R3, LSL #8//r3 after left-shift and R2-combined short value-&GT;R3
840C:E54B301A STRB R3, [FP, #-26]//R3 in the short value (low)-> variable St Low
8410:E1A03443 mov r3, R3, ASR #8//R3 8-bit right shift-&GT;R3
8414:e54b3019 STRB R3, [FP, #-25]//R3 in the short value (high)-> variable St high

How did 0x30201040 come from? Thought for a long time also do not understand.
Read ARM books found that if the coprocessor CP15:c1:c0 1-bit and 22-bit are 0, the arm instruction LDR return value is memory (addr & ~3, 4) ROR ((addr & 3) * 8). The meaning of the first half of the sentence is to the 4 boundary down, in this case is 0x10960, and then take its content is 0x40302010, the second half in this case is the loop right 24 bit. Together look is 0x40302010 ROR = 0x30201040, and this example coincides with.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.