zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

C基本知识

2023-03-15 22:49:16 时间

1 C基本数据类型

C基本的数据类型说明:

数据类型

2 字节序

字节序_1

测试代码:

#include <stdio.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, int len)
{
    int i;

    for (i = 0; i < len; i++) {
        printf(" %.2x", start[i]);
    }
    printf("
");
}

int main(void)
{
    int x = 0x01234567;

    show_bytes((byte_pointer)&x, sizeof(x));

    return 0;
}

编译运行测试:

$ gcc endian.c
$ ./a.out
 67 45 23 01

可以看出,当前我运行的机器是小端序。

3 结构体

参考:C语言技术天花板【结构体】一节课掌握_哔哩哔哩_bilibili

结构体中成员排列的规则:

  1. 结构体成员的内部偏移量(内部地址),要被这个成员的数据类型的大小整除。

    struct test {
        int   a; /* [Byte][Byte][Byte][Byte] */
        char  c; /* [Byte][0x00] */
        short s; /* [Byte][Byte] */
    };
    
    /* 结构体的内存大小 */
    sizeof(struct test) = 8;
    
    /* 结构体中的内存分布,可看出成员c后面填充了1Byte的0x00 */
    struct test test1 = {0};
    test1.a = 0x12345678;
    test1.c = 0xbb;
    test1.s = 0xccdd;
    
    (gdb) x /8bx &test1
    0x7fffffffe110: 0x78    0x56    0x34    0x12    0xbb    0x00    0xdd    0xcc
    
  2. 整个结构体的大小,必须是最大成员的size的整数倍,否则就需要在末尾填充空白字节。

    struct test {
        int   a; /* [Byte][Byte][Byte][Byte] */
        char  c; /* [Byte] */
    };
    
    /* 结构体的内存大小 */
    sizeof(struct test) = 8;
    
    /* 结构体中的内存分布,可看出成员c后面填充了3Byte的0x00 */
    (gdb) x /8bx &test1
    0x7fffffffe110: 0x78    0x56    0x34    0x12    0xbb    0x00    0x00    0x00
    
  3. 对于结构体中的结构体,按照结构体展开之后的内存对齐来处理。

    struct test1 {
        int a;   /* [Byte][Byte][Byte][Byte] */
        short s; /* [Byte][Byte][0x00][0x00] */
    };
    
    struct test {
        int   a; /* [Byte][Byte][Byte][Byte] */
        char  c; /* [Byte][0x00][0x00][0x00]*/
        struct test1 s;
    };
    
    /* 结构体的内存大小为16,根据规则1,成员c后面补充3Bytes的0x0,根据规则2,s.s成员后面补充2Bytes的0x0 */
    sizeof(struct test) = 16;
    
    /* 结构体中的内存分布 */
    struct test test1 = {0};
    test1.a = 0x12345678;
    test1.c = 0xff;
    test1.s.a = 0xaabbccdd;
    test1.s.s = 0x9988;
    (gdb) x /16bx &test1
    0x7fffffffe100: 0x78    0x56    0x34    0x12    0xff    0x00    0x00    0x00
    0x7fffffffe108: 0xdd    0xcc    0xbb    0xaa    0x88    0x99    0x00    0x00
    
  4. 认为指定特殊的对齐规则,使用#pragma pack(n)指定每个成员的其实地址,按照n来对齐,覆盖第一条规则。如果整个n比第一条规则对齐还要大,那么就取小的。

    #pragma pack(2)
    struct test1 {
        int a;   /* [Byte][Byte][Byte][Byte] */
        short s; /* [Byte][Byte] */
    };
    
    struct test {
        int   a; /* [Byte][Byte][Byte][Byte] */
        char  c; /* [Byte][0x00] */
        struct test1 s;
    };
    
    /* 结构体的内存大小为12,根据规则4,成员c后面补充1Bytes的0x0 */
    sizeof(struct test) = 12;
    
    /* 结构体中的内存分布 */
    struct test test1 = {0};
    test1.a = 0x12345678;
    test1.c = 0xff;
    test1.s.a = 0xaabbccdd;
    test1.s.s = 0x9988;
    (gdb) x /12bx &test1
    0x7fffffffe110: 0x78    0x56    0x34    0x12    0xff    0x00    0xdd    0xcc
    0x7fffffffe118: 0xbb    0xaa    0x88    0x99
    
    #pragma pack(8)
    struct test1 {
        int a;   /* [Byte][Byte][Byte][Byte] */
        short s; /* [Byte][Byte] */
    };
    
    struct test {
        int   a; /* [Byte][Byte][Byte][Byte] */
        char  c; /* [Byte][0x00] */
        struct test1 s;
    };
    
    /* 规则1生效 */
    sizeof(struct test) = 16;
    
  5. 不使用任何对齐,直接存放数据的方式,使用#pragma pack(1)

    #pragma pack(1)
    struct test1 {
        int a;   /* [Byte][Byte][Byte][Byte] */
        short s; /* [Byte][Byte] */
    };
    
    struct test {
        int   a; /* [Byte][Byte][Byte][Byte] */
        char  c; /* [Byte] */
        struct test1 s;
    };
    
    /* 结构体的内存大小为11,各个成员之间不会填充0x0 */
    sizeof(struct test) = 11;
    
    /* 结构体中的内存分布 */
    struct test test1 = {0};
    test1.a = 0x12345678;
    test1.c = 0xff;
    test1.s.a = 0xaabbccdd;
    test1.s.s = 0x9988;
    (gdb) x /11bx &test1
    0x7fffffffe110: 0x78    0x56    0x34    0x12    0xff    0xdd    0xcc    0xbb
    0x7fffffffe118: 0xaa    0x88    0x99