C language foundation (8)

byte alignment

Alignment rules for members in the structure:
1. Our structure variable itself is in a 4-byte aligned position, and the compiler helps us do it.
2. The first member is stored from the address where the structure starts. This element, how many bytes it occupies, is determined by the next element.
3. The entire member variable itself is aligned, and it is not over yet.
4. The entire structure should be the smallest integer multiple of the default byte alignment.
The default byte alignment of the structure: the type with the largest member variable occupies the bytes

#include<stdio.h>

typedef struct data
{
        int a;               // 4
        char b;             // 1 + 1(填充)
        short c;           // 2    最后整个结构体自身还要对齐
}D;
int main(void)
{
    printf("sizeof(D)=%d.\n",sizeof(D));
    return 0;
}
结果为8byte

Notice:

struct data
{
    int a;
    struct data s;   // 1.此时结构体类型(定义)不完整  2.C语言不允许
}s;
int main(void)
{
    unsigned short a = 0x1234;  
    unsigned char * p1 = (unsigned char *)&a, i = 8;
    //*p1 << i,就产生了临时变量,内存中你不知道地址,但是有一个默认类型(int)
    printf("sizeof(*p1 << i) = %d.\n", sizeof(*p1 << i));
    printf("0x%x.\n", *p1 <<= i);    // printf("%d.\n", a *= 2);
    printf("0x%x.\n", *(p1+1));
}
结果如下:sizeof(*p1 << i)=4
        0x0
        0x12
#include<stdio.h>

struct data
{
        int a;                              // 4 + 4(padding)

        struct data *p_next;              //64bit机器指针永远永远占8字节
}S;
int main(void)
{
    printf("sizeof(S)=%d.\n",sizeof(S));
    return 0;
}
结果为16byte

nesting of structures

#include<stdio.h>
struct data1
{
        int a;
        short b;
        int c;
        double e;
};//24

typedef struct data
{
        char a;//2
        short b;//2
        int c;//4
        struct data1 s;//24 
        char ch;//8
}S;

int main(void)
{
    printf("sizeof(S)=%d.\n",sizeof(S));
    return 0;
}
结果为40

field alignment

Bit field: dedicated to the structure, the type of the structure member must be: int || unsigned int
Sometimes, the data represented by the structure member is very small, so it is represented by a few bits.
0 field, inaccessible, just occupying the remaining bits in the whole word, all write 0
unnamed field, inaccessible, just occupying
word (word)=32bit
The next field is not enough to store the remaining words, and a new one must be created Character. Fields cannot span words.
If the data range represented by the field is exceeded, the result is unpredictable.
If the last word is not filled, it will be filled and returned. The
address of the field is unacceptable.

#include <stdio.h>
struct data1
{
    unsigned a : 1;     // 1就是一个bit,范围:0~1
    int : 31;           // 无名字段,不可访问,只是占位
    unsigned b : 2;     // 2就是2个bit,范围:0~3
    unsigned c : 2;   // 28位 
}s1;

int main(void)
{
    printf("szieof(s1) = %d.\n", sizeof(s1));
    return 0;
}
结果为8byte,同时也是2word

especially:

struct
{
    int a:1;//此时a只有一位且仅为符号位,取值范围为(-1~0)
};

alignment instruction

#pragma pack(n) (1、2、4、8、.....)
#pragma pack()

These two are used together to represent an interval, and only the structures in this interval enjoy this treatment.
Set alignment.
If n is set to 1, it is not aligned to
1, making full use of memory space, sacrificing speed and reducing access efficiency.
2. Improve efficiency and performance, sacrificing memory space.
Summary: The alignment you specify and the default alignment of the structure itself, whichever is the smallest.

#include <stdio.h>
#include <stdlib.h>

#pragma pack(2)
struct data                 // 16
{
    int a;
    char b;
    double c;
}s;

struct data1
{
    char ch;
}s1;
#pragma pack()

Macro to check for system errors

Once it occurs, a system error will generate an error number (errno), corresponding to the corresponding error string.
The C standard defines two values, EXIT_SUCCESS and EXIT_FAILURE, which can be used as parameters of exit() to indicate whether the exit is successful or not.
exit (parameter) is passed to the parent process, or the shell terminal

#define handle_error(msg)   do{perror(msg); exit(EXIT_FAILURE);}while(0)

Linux built-in macros

Two macros in the linux kernel: widely used in driver applications.
off_set_of(type, member) calculates the offset of the elements in the structure contain_of(
ptr, type, member), ptr is the pointer to the member in the structure, and the first address of the structure is calculated by calling this macro. Contains two lines of code (expression formula), you must add {}.
These two macros: kernel double linked list.

分析:
#define off_set_of(type, member)  ((long)&(((type *)0)->member))
1、(type *)0指向结构体零地址                                         
2((type *)0)->member得到了结构体某个成元变量名    
3、给这成员变量名,取地址(相对于零地址),此时&(((type *)0)->member)表示是指针类型 
4、强制类型转换成(long)

#define container_of(ptr, type, member)   ({typeof(((type *)0)->member) *_mptr = ptr;(type *)((char *)_mptr-off_set_of(type, member));})
1、得到结构体成员变量的类型
2、指针赋值(得到真实成员变量的地址值)
3、减去偏移量得到一个数字,该数字和结构体本身首地址在数值上一样
4、最后强制类型转换为结构体指针类型

Take a chestnut:

#include <stdio.h>

#define off_set_of(type, member)  ((long)&(((type *)0)->member))
#define container_of(ptr, type, member)     ({typeof(((type *)0)->member) *_mptr = ptr;(type *)((char *)_mptr-off_set_of(type, member));})

struct da
{
    int a;
    short b;    
    int c;
    double e;
};                      // 16
struct data
{
    char a;
    short b;
    int c;              // 8
    struct da s;    // 16
    char ch;
}s = {1, 3, 10, 3.14, 1.41};
//1、不会因为有结构体成员,而影响你的基本类型,决定默认对齐
//2、里面的结构体对齐方式,已经在外面决定了(遍历整个完整结构体)

int main(void)
{
    printf("sizeof(s) = %d.\n", sizeof(s));
    //结构体自身的首地址
    printf("&s = %p.\n", &s);
    struct da *p = container_of(&s.s.b, struct da, b);
    printf("p = %p.\n", p);
    printf("&s.s = %p.\n", &s.s);
    return 0;
}
p->a == (struct data *)0->a;
/*
//让你明白强制转换0地址
struct data *p;     
unsigned long a = 0;        
p = (struct data *)a;  
p->a == (struct data *)0->a;
*/

About typeof

The parameters in typeof() and () can be variable names or expressions.
typeof(int) p

int *p, a;
typeof(p) p_a = &a;//将p_a的类型转换为p的类型,即指针类型

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325919978&siteId=291194637