See Memory through bit field (bit fields)

Source: Internet
Author: User
Tags first row


1. Bit Field Introduction

A bit field is a contiguous set of bits in a signed char, unsigned char, signed int, unsigned int. Bit fields a structure declaration is created, which declares a label for each field and determines the width (number of bits) of the field. Take the int type as an example, such as:

struct field{
unsigned int a:1;  A accounted for 1 bits
unsigned int b:2;  b accounted for 2 bits
unsigned int c:2;  C accounted for 2-bit
unsigned int d:3;  D accounted for 3 bits
};                   8-bit struct field field is accounted for altogether
;
FIELD.A = 1;         A =  01 (binary)
filed.b = 2;         b =  10 (binary)
filed.c = 3;         c =  11 (binary)
field.d = 3;         D = 011 (binary)  Note: Do not exceed the capacity of the field when assigning values, such as: the maximum value for D is 7 (111)

The variable filed is stored in an int-sized storage unit, and only eight of them are used in this example.
The total number of bits declared exceeds the size of one unsigned int, and that will be used for the next unsigned int storage location. A field is not allowed to span boundaries between two unsigned int. The compiler automatically shifts one such field definition so that the field is aligned at the unsigned int boundary. When this happens, an unnamed hole (unnamed hole) is left in the first unsigned int.
You can use unnamed fields to "populate" (PAD) unnamed holes.
If you use an unnamed field with a width of 0, the next field is forced to align with the next integer. Such as:

struct field{
unsigned int a:1;
unsigned int   : 2;  There is a two-bit gap between A and C
unsigned int c:1;
unsigned int   : 0;
unsigned int d:1;  Field d is stored in the next int
};

Note: bit fields are machine-dependent and the order in which fields are placed into int. Some machines are left-to-right (using high-level) and others are right-to-left (using low-level first).

The fields are placed in order from low to high on my computer. The following example is sufficient to illustrate everything.
How the data is stored in memory. Big-endian (Big-endian) or small (Little-endian). What is the way the data is pressed into the stack and the local variables allocate space in the stack when the function is called? The following example is sufficient to illustrate everything.

1) Little-endian is the low byte emissions in the memory of the lower address, high-byte emissions at the high address of the memory.
2) Big-endian is the high-bit bytes emitted at the low address of the memory, low bytes emitted in the memory of the higher address.


Of course, there is a simpler way to get the CPU to use Big-endian or Little-endian data read-write mode , and the following example is enough to explain everything.

2. The following example illustrates everything
Look at the code first:

#include <stdio.h> int main (void) {typedef struct FIELD {unsigned int a:4;
        unsigned int b:4;
        unsigned int c:4;
        unsigned int d:4;
        unsigned int e:4;
        unsigned int f:4;
        unsigned int g:4;   unsigned int h:4;
    int occupies 4 bytes, 32 bits, total 8 fields, 4 bits per field}field;  typedef struct CHAR {unsigned char a:4;
    Char occupies a byte, 8 bits, a total of 2 fields, 4 bits per field unsigned char b:4;

    }char;     int in = 0x13572468;                 Integer variable assignment, hex Char ch;             Char type bit field variable fields;  int type bit field variable int *add_ch, *add_ch_3;   The pointer add_ch points to the address of CH,//pointer add_ch_3 points to the address of 3 bytes smaller than CH's address ch.a = 15;   0xF ch.b = 14; 0xE field.a = 8; 0x8 field.b = 7; 0x7 FIELD.C = 6; 0x6 field.d = 5; 0x5 FIELD.E = 4; 0x4 FIELD.F = 3; 0x3 FIELD.G = 2; 0x2 field.h = 1;           0x1 add_ch = (int *) (&AMP;CH); Pointer add_ch to the address of ch Add_ch_3 = (int *) (&AMP;CH-0X03);
       The pointer add_ch_3 points to the address of the 3 byte unit smaller than the CH address printf ("\nthe second byte \" 24\ "of the \" in = 0x13572468\ "to char is \"%c\ "\ n",    * (((char *) (&in) + 0x1)); Print in the second byte of the content, if not (char *), then the integer pointer plus one is added four//byte unit address printf ("sizeof (IN) =%d\n", s
    Izeof in);
    printf ("sizeof (ch) =%d\n", sizeof ch);

    printf ("sizeof (field) =%d\n\n", sizeof field);         printf ("&in =%p\n", &in);         In the address printf ("&ch =%p\n", &ch);    The address of CH is printf ("&field =%p\n\n", &field);
    The address of field is printf ("in =% #X \ n", in);
    printf ("ch =% #X \ n", ch);    printf ("field =% #X \ n", field);
    Hex print in, ch, field printf ("Add_ch_3 = (&ch-0x03) =%p\n", add_ch_3);

    printf ("*add_ch_3 = * (&ch-0x3) =% #X \ n", *add_ch_3);
    printf ("add_ch =%p\n", add_ch);

    printf ("*add_ch =% #X \ n", *add_ch);
return 0;
 }

Then look at the output (debug mode):



Draw the memory stack from the output, as shown below:



The byte at address 0xbffff705 is 0x24, which is exactly the ASCII of the character ' $ ', so the first line of the program prints out the ' $ ' character. From here you can see that the CPU uses a small-end read-write mode for memory.
Convert CH address 0xffff703 to an integer address type, and print this address with a value of 0X572468EF, where a high of 3 bytes is 3 bytes lower in the value.
The value of the label ①, ②, ③ is indeterminate.
In addition, in the process of executing the main function, the variables are pressed into the stack in the order in which they are declared (the variable is allocated storage space sequentially in the stack).
With memory dump, you can see:



The byte value corresponding to 24 in the first row is ' $ '.
Through the above analysis, all questions at a glance.
The following is a simpler example of getting CPU-to-memory data read and write mode.
The code is as follows:

#include <stdio.h>

int main (void)
{
    union {
        unsigned int  A;
        unsigned char b;
    } C;
    C.A = 1;
    if (c.b = = 1)
        printf ("little-endian\n");
    else
        printf ("big-endian\n");

    return 0;
}

Because The union union is stored in the order that all members are stored from the low address, this feature makes it easy to get the CPU to use Little-endian or Big-endian mode to read and write to memory.


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.