0%

C语言数组

消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。目前使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ。消息的消费模式分Push、Pull两种,或者两者兼具,RabbitMQ的消费模式就是兼具Push和Pull。

一、基础

      在C语言中,数组可以存储一个固定大小的相同类型元素的顺序集合,且所有的数组都是连续的内存空间。

二、柔性数组

  1. 在C99中,结构体中的最后一个元素可以是未知大小的数组,这个数组就叫做柔性数组成员,也称伸缩性数组成员,其前面至少要存在一个其他成员。官方说明:As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member.。C99支持incomplete typeint a[]格式,不支持zero arrayint a[0]格式(有的编译器支持)。关于incomplete说明:incomplete types(types that describe objects but lack information needed to determine their sizes).。柔性数组成员特性如下:

    • 柔性数组不占内存,即sizeof返回的这种结构体大小时不包括柔性数组的内存
    • 柔性数组成员必须定义在结构体里面且为最后元素
    • 结构体中不能单独只有柔性数组成员
    • 包含柔性数组成员的结构体用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小以适应柔性数组的预期大小。
    • C语言数据类型可分为四大类,即基本类型(数值类型(又分为整型和实数型)、字符串)、构造类型(数组、结构体、共用体、枚举)、指针类型、空类型。对于大部分数据类型,在其声明后所占的内存空间就已确定,如char a占1个字节,int b[10]则占40个字节,结构体所占内存为成员所占空间的总和(不考虑内存对齐的情况,实际不是取的和),共用体则为最大成员的所占的空间。
  2. 结构体是比较常用的一种数据类型,有时需要在结构体中存放一个长度是动态的成员,此时一般又两种做法:

    • 定义一个指针成员,指针指向动态的内存空间
      • 分配和释放内存都需要进行两次。运行后可知,结构体内存和指针p指向的字符串内存是不连续的,
    • 使用柔性数组成员
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stddef.h>

    // #pragma pack(32);

    typedef struct Test {
    long double b;
    int a;
    char *p;
    } Test;

    int main()
    {
    Test *t = (Test *)malloc(sizeof(Test));

    char *str = (char *)malloc(sizeof(char) * 10);
    strcpy(str, "hello");

    t->p = str;

    printf("指针p的内容:%s\n", (t->p));
    printf("t的地址为:%p\n", t);

    printf("char *大小为:%d\n", sizeof(char *));

    printf("t.b的地址为:\t%p\n", &(t->b));
    printf("t.a的地址为:\t%p\n", &(t->a));
    printf("t.p本身的地址为:%p\n", &(t->p));
    printf("t.p内容的地址为:%p\n", (t->p));

    printf("t.b的偏移量为:%d\n", offsetof(struct Test, b));
    printf("t.a的偏移量为:%d\n", offsetof(struct Test, a));
    printf("t.p的偏移量为:%d\n", offsetof(struct Test, p));//64位机器指针固定占8个字节

    printf("t的内存大小为:%lu", sizeof(Test));

    free(t);
    free(t->p);

    return 0;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <string.h>
#include <stdlib.h>

typedef struct Test {
int a;
char p[];
} Test;

int main() {
Test *t = (Test*)malloc(sizeof(Test) + sizeof(char) * (10+1));
strcpy(t->p, "hello");

printf("%s\n", (t->p));
printf("Address:\n");
printf("t\t %p\n", t);
printf("t.a\t %p\n", &(t->a));
printf("t.p\t %p\n", (t->p));
free(t);

return 0;
}
  1. 参考

三、声明数组的几种方式

定义数组的标准语法:

1
type arrayName [ arraySize ];
  • type可以是任意有效的C数据类型
  • arrayName是定义的数据名
  • arraySize必须是一个大于零的整数常量
  1. 第一种:只声明数组名和数组大小
1
int arr[10];
  1. 第二种:声明并初始化数组元素
    • 数组的大小则为初始化时元素的个数
1
int arr[] = {1,2,4};
  1. 第三种:声明并初始化部分数组元素
    • 大括号{}之间的值的数目不能大于方括号[]中指定的元素数目。
1
int arr[10] = {1,2};
  1. 第四种:通过new关键字
    • 只有C++支持
1
int *arr  = new int[10];

四、参考

  1. 参考一