11-C语言结构体(下篇)

一、结构体指针变量

结构体指针变量:本质上是一个指针变量,保存的是结构体变量的地址。

1.结构体变量的地址

结构体变量的地址:对结构体变量名取地址。

  • 代码演示
typedef struct stu
{
    char name[32];
    int age;
    float score;
}STU;

int main()
{
    STU jack = {"jack", 18, 88.8};
    printf("%p\n", &jack);
    printf("%p\n", &jack.name);
    return 0;
}
  • 运行结果
000000472c7ffaa0
000000472c7ffaa0
  • 说明:
    1. 结构体变量地址与结构体首个成员地址相同,都指向同一个位置;
    2. 结构体变量地址为 STU *类型,结构体首个成员地址为char **类型,即二者取值的宽度与指针偏移的跨度不相同。

2.结构体指针

2.1结构体指针变量的定义

结构体指针变量定义:结构体类型 *指针变量名 = &结构体变量

  • 代码演示
int main()
{
    STU jack;
    STU *p = &jack;

    // 键盘输入为结构体成员赋值
    printf("请输入(姓名 年龄 分数):");
    scanf("%s %d %f", p->name, &p->age, &p->score);

    // 访问结构体成员
    printf("我叫:%s,今年%d岁,考了%.2f分\n", jack.name, jack.age, jack.score);
    printf("我叫:%s,今年%d岁,考了%.2f分\n", (*p).name, (*p).age, (*p).score);
    printf("我叫:%s,今年%d岁,考了%.2f分\n", p->name, p->age, p->score);
    return 0;
}
  • 运行结果
请输入(姓名 年龄 分数):jack 18 88.8
我叫:jack,今年18岁,考了88.80分
我叫:jack,今年18岁,考了88.80分
我叫:jack,今年18岁,考了88.80分
  • 说明:
    1. 结构体成员可以通过结构体变量访问,也可以通过结构体指针访问;
    2. 当通过结构体变量通过.访问结构体成员,结构体指针或地址通过->访问结构体成员。

2.2结构体数组在栈区,指针成员指向堆区

首先看清要求:类型为结构体数组,存储在栈区,结构体数组中的结构体对象中存在指针成员,且指针成员指向堆区。

  • 代码演示:
int main()
{
    // 定义一个结构体数组
    STU stu_s[5];
    // 为结构体指针成员申请堆区空间
    int i = 0;
    for (i = 0; i < 5; i++)
    {
        stu_s[i].name = (char *)malloc(32);
        if (NULL == stu_s[i].name)
        {
            printf("内存申请失败\n");
            return 0;
        }
    }

    // 键盘输入赋值
    printf("请输入(姓名 年龄 分数):");
    for (i = 0; i < 5; i++)
    {
        scanf("%s %d %f", stu_s[i].name, &stu_s[i].age, &stu_s[i].score);
    }

    // 遍历结构体成员内容
    printf("-----------------------------------\n");
    for (i = 0; i < 5; i++)
    {
        printf("我叫:%-7s,今年%02d岁,考了%.2f分\n", stu_s[i].name, stu_s[i].age, stu_s[i].score);
    }

    // 释放堆区空间
    for (i = 0; i < 5; i++)
    {
        if (NULL != stu_s[i].name)
        {
            free(stu_s[i].name);
            stu_s[i].name == NULL;
        }
    }
    return 0;
}
  • 运行结果
请输入(姓名 年龄 分数):小明 18 88.8
小红 20 86.6
王刚 25 75
李华 18 92
王翠花 28 68
-----------------------------------
我叫:小明   ,今年18岁,考了88.80分 
我叫:小红   ,今年20岁,考了86.60分
我叫:王刚   ,今年25岁,考了75.00分
我叫:李华   ,今年18岁,考了92.00分
我叫:王翠花 ,今年28岁,考了68.00分
  • 说明:当结构体存在指针成员指向堆区的时候,要先为指针成员申请堆区空间,再为其赋值操作,用完记得释放堆区空间。

2.3结构体数组在堆区,指针成员指向堆区

首先类型为数组,数组存储在堆区,数组每个成员为结构体类型,结构体某些成员为指针,指针指向堆区空间。既然结构体数组存储的堆区,就需要通过指针变量指向堆区空间。

  • 代码演示
int main()
{
    // 定义一个结构体指针,并为其申请堆区空间
    STU *stu_s = (STU *)calloc(5, sizeof(STU));
    // 为结构体指针成员申请堆区空间
    int i = 0;
    for (i = 0; i < 5; i++)
    {
        (stu_s + i)->name = (char *)malloc(32);
        if (NULL == (stu_s + i)->name)
        {
            printf("内存申请失败\n");
            return 0;
        }
    }

    // 键盘输入赋值
    printf("请输入(姓名 年龄 分数):");
    for (i = 0; i < 5; i++)
    {
        scanf("%s %d %f", (stu_s + i)->name, &(stu_s + i)->age, &(stu_s + i)->score);
    }

    // 遍历结构体成员内容
    printf("-----------------------------------\n");
    for (i = 0; i < 5; i++)
    {
        printf("我叫:%-7s,今年%02d岁,考了%.2f分\n", (stu_s + i)->name, (stu_s + i)->age, (stu_s + i)->score);
    }

    // 释放堆区空间
    for (i = 0; i < 5; i++)
    {
        if (NULL != (stu_s + i)->name)
        {
            free((stu_s + i)->name);
            (stu_s + i)->name == NULL;
        }
    }
    if (NULL != stu_s)
    {
        free(stu_s);
        stu_s == NULL;
    }
    return 0;
}
  • 运行结果
请输入(姓名 年龄 分数):隆冬强 43 60
王大锤 32 75
旺财 10 95.5 
常威 35 25
来福 30 33
-----------------------------------
我叫:隆冬强 ,今年43岁,考了60.00分 
我叫:王大锤 ,今年32岁,考了75.00分 
我叫:旺财   ,今年10岁,考了95.50分
我叫:常威   ,今年35岁,考了25.00分 
我叫:来福   ,今年30岁,考了33.00分
  • 说明:
    1. 先要申请堆区空间,再使用;
    2. 申请的时候先申请结构体数组的堆区空间,再申请结构体指针成员指向的堆区空间;
    3. 释放堆区空间的时候,先释放结构体指针成员指向的堆区空间,再释放结构体数组的堆区空间;
    4. 结构体数组的每个成员为STU类型,那指向堆区的指针变量类型为STU*

2.4结构体指针数组在堆区,每个元素指向堆区,元素的指针成员指向堆区

  • 分析:本质上是一个数组,数组在堆区,数组每个元素为结构体指针变量,结构体指针变量指向堆区,结构体中有指针成员,且指针成员也指向堆区。

  • 代码演示:

int main()
{
    int n = 0;
    printf("请输入学生数量:");
    scanf("%d", &n);
    // 为结构体指针数组申请堆区空间
    STU **stu_s = (STU **)calloc(n, sizeof(STU *));

    // 为结构体指针申请堆区空间
    int i = 0;
    for (i = 0; i < n; i++)
    {
        // *(stu_s + i) = (STU *)malloc(sizeof(STU *));
        stu_s[i] = (STU *)malloc(sizeof(STU *));
        if (NULL == stu_s[i])
        {
            printf("内存申请失败\n");
            return 0;
        }
        // 为指针成员申请堆区空间
        // (*(stu_s + i))->name = (char *)malloc(32);
        stu_s[i]->name = (char *)malloc(32);
        if (NULL == stu_s[i]->name)
        {
            printf("内存申请失败\n");
            return 0;
        }
    }

    // 键盘输入为结构体成员赋值
    printf("请输入(姓名 年龄 分数):");
    for (i = 0; i < n; i++)
    {
        scanf("%s %d %f", stu_s[i]->name, &stu_s[i]->age, &stu_s[i]->score);
    }

    // 遍历数据
    printf("-----------------------------------\n");
    for (i = 0; i < n; i++)
    {
        printf("我叫:%-7s,今年%02d岁,考了%.2f分\n", stu_s[i]->name, stu_s[i]->age, stu_s[i]->score);
    }

    // 释放堆区空间
    for (i = 0; i < n; i++)
    {
        // 释放指针成员指向的堆区空间
        if (NULL != stu_s[i]->name)
        {
            free(stu_s[i]->name);
            stu_s[i]->name == NULL;
        }
        // 释放结构体指针指向的堆区空间
        if (NULL != stu_s[i])
        {
            free(stu_s[i]);
            stu_s[i] == NULL;
        }
    }
    // 释放结构体指针数组的堆区空间
    if (NULL != stu_s)
    {
        free(stu_s);
        stu_s == NULL;
    }
    return 0;
}
  • 运行效果
请输入学生数量:3
请输入(姓名 年龄 分数):张大炮 32 85
吕小布 30 83.5
曾小莲 29 78.5
-----------------------------------
我叫:张大炮 ,今年32岁,考了85.00分 
我叫:吕小布 ,今年30岁,考了83.50分 
我叫:曾小莲 ,今年29岁,考了78.50分
  • 说明:
    1. 此案例中:数组的元素为结构体指针变量,其类型为STU *,则指向结构体指针数组的堆区空间的指针变量为一个二级指针STU **;
    2. 申请堆区空间的时候先申请结构体指针数组的堆区空间,再申请结构体指针指向的堆区空间,再申请结构体指针变量指向的堆区空间;
    3. 释放空间的时候,先释放结构体指针变量指向的堆区空间,再释放结构体指针指向的堆区空间,最后释放存储结构体指针数组的堆区空间;
    4. 从上面几个案例可以总结出:堆区空间在申请的时候,先申请外层堆区空间,再逐级申请内层堆区空间;释放的时候先逐层释放内层堆区空间,再释放外层堆区空间;
    5. 涉及到指针、数组的时候,使用数据的方式不止一种,可以根据习惯选择最方便的方案;数据存储的空间分布比较复杂的时候,拆开逐层分析。

3.结构体指针成员为函数指针

C语言中结构体成员不能为函数名,但是可以是函数指针。

  • 代码演示
void stu_action(char *name)
{
    printf("%s正在打篮球\n", name);
}

typedef struct stu
{
    char *name;
    int age;
    // 结构体成员为函数指针类型
    void (*action)(char *);
}STU;

int main()
{
    // 定义结构体变量并初始化
    STU jack = {"jack", 18, stu_action};
    jack.action(jack.name);
    return 0;
}
  • 运行结果
jack正在打篮球
  • 说明:结构体成员为函数指针的时候,在定义这个结构体成员前应先定义函数或声明函数。

二、结构体默认对齐规则

结构体占用的空间大小并不是我们想象中的将各种类型的数据的空间大小累加起来,而是遵循一定的规则。

1.结构体的大小

  • 代码演示
typedef struct stu
{
    char ch;
    int a;
}STU;

int main()
{
    printf("%zu\n", sizeof(STU));
    return 0;
}
  • 运行结果
8
  • 上面的案例中:结构体成员有一个char类型的变量,1字节;一个int类型的变量,4字节。但结构体类型的大小却占8字节,因为为了方便数据的读写,结构体有其默认的对齐规则。其内层分布见下图:

在这里插入图片描述

2.结构体对齐步骤

2.1成员为基本类型

我们需要将结构体在内存中的存储抽象为一行一行来看:

  1. 确定分配单位:一行分配多少字节,结构体中最大的基本类型长度就是分配单位,上面案例分配单位就是一个int的长度4字节;

  2. 成员的偏移量:相对于结构体的起始位置的偏移字节数,成员自身大小的整数倍,同时注意后一个成员要在前一个成员的后面,即使前一个成员前面有足够空间存储它;

    typedef struct stu
    {
        char ch1;
        int a;
        char  ch2;
    }STU;
    
    int main()
    {
        printf("%zu\n", sizeof(STU)); // 12
        return 0;
    }
    

    在这里插入图片描述

    上面案例,成员char ch2;定义在成员int a后面,即使int a前面有空间放ch2,也得放在后面。

  3. 结构体总大小:分配单位的整数倍,即分配单位长度乘分配的行数;

  4. 为了节约内存,定义结构体类型的时候,需要合理分配成员先后顺序;

    typedef struct stu
    {
        char ch1;
        char  ch2;
        short b;
        int a;
    }STU;
    
    int main()
    {
        printf("%zu\n", sizeof(STU)); // 8
        return 0;
    }
    

    这种写法多存储了一个short类型的数据,但消耗的空间比上面的写法还节约了4字节,其内存分布:

    0123
    ch1ch2bb
    4567
    aaaa

2.2数组成员的对齐

结构体中最大的基本类型长度为分配单位,数组不是基本类型,因此不能将数组看成一个整体,而是把数组拆成一个个基本类型来分布。

  • 代码演示
typedef struct stu
{
    char ch1;
    char  ch2;
    short b;
    int a;
    char str[5];
    short c;
}STU;

int main()
{
    printf("%zu\n", sizeof(STU));
    return 0;
}
  • 运行结果
16
  • 说明:如果结构体成员为字符数组,就将数组拆分为对应个数字符分布,如果数组元素的基本类型长度最大,那么分配单位就为数组元素基本类型的长度,上面定义的结构体的内存分布为:
0123
ch1ch2bb
4567
aaaa
891011
str[0]str[2]str[3]str[4]
12131415
str[5]cc

2.3结构体嵌套对齐

  1. 分配单位等于所有结构体中最大的基本类型,如果内层结构体的基本类型最大,本质上也是外层基本类型最大,因为内层属于外层,但如果内层最大基本类型小于外层最大基本类型,内层分配单位为其自身最大基本类型长度;
  2. 结构体成员的偏移量等于该结构体最大基本类型整数倍,结构体成员中的成员偏移量是相对于结构体成员的偏移量而言的;
  • 代码演示
struct test
{
    char a;
    int b;
};

typedef struct stu
{
    char ch1;
    struct test tes;
    short c;
}STU;

int main()
{
    printf("%zu\n", sizeof(STU)); // 16
    return 0;
}

其内存分布:

0123
ch1
4567
a
891011
bbbb
12131415
cc
  • 案例:下方结构体的内存大小为多少
struct A
{
    char a;
    short b;
};

struct B
{
    short c;
    struct A d;
    short e;
    int f;
};

int main()
{
    printf("%zu\n", sizeof(struct B));
    return 0;
}
  • 答案为12字节,对照下面的内存分布表逐步分析:
0123
cca
4567
bbee
891011
ffff
  1. 外层基本分配单位为4字节,c先占两个字节;
  2. 结构体成员d的偏移量等于该结构体最大基本类型short整数倍,因此结构体成员偏移量为2,分配单位为2;
  3. 结构体成员从2号位开始,a占2号位,后一个位short b,3不是2的倍数,b占4、5号位;
  4. 内层结构体对齐完成,接着层结构体分配单位的整数倍后面,6号位满足内层结构体分配单位的整数倍,e内层整数倍,e占6、7位;
  5. 8为int长度的整数倍,f占8~9四个字节。

三、结构体强制对齐规则

1.强制对齐

在定义结构体类型之前写上:#pragma pack (value)指定对齐值 value,但value并非就是分配单位,真正的分配单位是min(value,结构体中最大的基本类型长度),即:如果给定的value值为8,但结构体中成员最大长度为4,那么分配单位是4,取给定值和成员类型最大值两者的最小值。

  • 代码演示·
#pragma pack(1)
struct A
{
    char a;
    int b;
};

int main()
{
    printf("%zu\n", sizeof(struct A)); // 5
    return 0;
}

将value值设定为1的时候,结构体总大小就是每个成员大小的累加和了。

  • 验证分配单位是min(value,结构体中最大的基本类型长度)
#pragma pack(8)
struct A
{
    int a;
    char b;
    int c;
};

int main()
{
    printf("%zu\n", sizeof(struct A));
    return 0;
}

如果上面代码的运行结果为16,则按照8字节分配,验证不成立,如果允许结果为12字节,则按照4字节分配,验证成立。

  • 运行结果
12

因此分配单位是min(value,结构体中最大的基本类型长度)

2.结构体位域

2.1位域的概念

结构体中成员所占空间以二进制位计算称之为位域或位段。

struct A
{
    unsigned  int a : 3;
};
  • 说明:
    1. 位域所占的位数,不能超过自身类型的二进制位数,如:上面案例 a 的位域占用位数不得超过32位;
    2. 位域的类型一般位无符号整数类型。

2.2位域赋值

  • 代码演示
struct A
{
    // 范围 0~7
    unsigned  int a : 3;
    int b : 3;
    unsigned  float c : 3; // 报错
};

int main()
{
    struct A obj;
    obj.a = 5;
    printf("%d\n", obj.a);

    obj.a = 10; // 1010
    printf("%d\n", obj.a); // 取3位010

    obj.b = 14;// 1110
    printf("%d\n", obj.b); // 110
    return 0;
}
  • 运行结果
5
2 
-2
  • 说明:
    1. 给位域赋值的时,注意不要超过它所占位的最大值。上面案例中赋值范围为0~7,10超过范围,其二进制数为 1010,只会取其后三位010,转化十进制为2;
    2. 位域为无符号整数,如果定义为有符号,取值时会把第一位看成符号位。上面案例:14二进制1110,取后三位110,第一位为符号位,为1,因此为负数,求十进制-2;
    3. 将位域定义为浮点数会直接报错。

2.3位域压缩

相邻且类型相同的位域称为相邻位域,相邻位域才能压缩。但是相邻位域压缩的位数不能超过自身类型的位数。

  • 代码演示
struct A
{
    // 范围 0~7
    unsigned  char a : 3;
    unsigned  char b : 4;
};

struct B
{
    // 范围 0~7
    unsigned  char a : 3;
    unsigned  char b : 4;
    unsigned  char c : 2;
};

int main()
{
    printf("%zu\n", sizeof(struct A));
    printf("%zu\n", sizeof(struct B));
    return 0;
}
  • 运行结果
1
2
  • 说明:
    1. 如果相邻位域压缩的位数超过自身类型的位数,会另起一行存储;
    2. 上面案例char位数为8,A 的位数和为7,用一个字节可以放;但 B 的位数和为9,一个字节放不下,需要两个字节,其中一个字节放成员 a 和 b,另外一个字节放 c(这里不会把 c 拆为两份)。

2.4位域分隔

当我们不希望相邻位域压缩在一块,想要将其分为两个单元存储时,可以将它们分隔。

  1. 直接另起一个存储单元

    struct A
    {
        // 范围 0~7
        unsigned  char a : 3;
        unsigned  char  : 0;
        unsigned  char b : 4;
    };
    
    int main()
    {
        printf("%zu\n", sizeof(struct A)); // 2
        return 0;
    }
    

    这种方式是直接在unsigned char : 0;后面另起了一个单元。

  2. 无意义位宽

    struct A
    {
        // 范围 0~7
        unsigned  char a : 2;
        unsigned  char  : 2;
        unsigned  char b : 4;
    };
    
    int main()
    {
        printf("%zu\n", sizeof(struct A)); // 2
        return 0;
    }
    

    这种方式是在两个位域间间隔了指定位数,如果两个位域与无意义位宽的和超过了一个单元,要另起一个单元。无意义位宽应用较广,寄存器单片机,网络通信都会用到。

四、其它构造类型

1.共用体

结构体的每个成员独立拥有一个空间,但共用体的所有成员共享同一块空间。共用体定义方式与结构体类似,只是将关键字struct换成了 union

  • 代码演示
union A
{
    char a;
    short b;
    int c;
};

int main()
{
    printf("%zu\n", sizeof(union A)); // 4
    return 0;
}
  • 说明:上面共用体中a b c 三个成员共享同一块空间,空间的大小由最大的成员大小决定。
  • 案例:下面代码计算结果:
union A
{
    unsigned char a;
    unsigned short b;
    unsigned int c;
};

int main()
{
    union A obj;
    obj.a = 10;
    obj.b = 20;
    obj.c = 256;
    printf("%u\n", obj.a + obj.b + obj.c);
    return 0;
}
  • 运行结果
512
  • 说明:因为后面的赋值会覆盖前面的赋值,因此最终共用体的值16进制表示位0x00 00 01 00,又因为成员操作空间大小由自身类型大小决定,因此a取到的值为0x00 00 = 0,b取到的值为0x01 00 = 256,c取到的值为0x00 00 01 00 = 256,求和为512.

2.枚举

枚举:将变量将要赋的值 一一列举出来。枚举定义方式与结构体类似,只是将关键字struct换成了 enum

  • 代码演示
enum DIRECTION {EAST, SOUTH, WEST = 8, NORTH};

int main()
{
    enum DIRECTION direction;
    direction = EAST;
    printf("%d %d %d %d\n", EAST, SOUTH, WEST, NORTH);
    return 0;
}
  • 运行结果
0 1 8 9
  • 说明:
    1. 在C语言里枚举值没有作用域的限制,一个枚举值只能定义一次;
    2. 枚举值默认从0开始递增,赋值的话默认从赋的值开始递增;
    3. 定义一个枚举变量,为其赋值只能赋枚举值,赋其它值没有任何意义。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/940118.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux普通用户使用sudo不需要输密码

1.root用户如果没有密码&#xff0c;先给root用户设置密码 sudo passwd root #设置密码 2.修改visudo配置 su #切换到root用户下 sudo visudo #修改visudo配置文件 用户名 ALL(ALL) NOPASSWD: ALL #下图所示处新增一行配置 用户名需要输入自己当前主机的用户名

百度面试手撕 go context channel部分学习

题目 手撕 对无序的切片查询指定数 使用context进行子协程的销毁 并且进行超时处理。 全局变量定义 var (startLoc int64(0) // --- 未处理切片数据起始位置endLoc int64(0) // --- 切片数据右边界 避免越界offset int64(0) // --- 根据切片和协程数量 在主线程 动态设…

任务一登录安全加固

1 &#xff08;1&#xff09;、&#xff08;2&#xff09; secpol.msc打开本地安全策略 2 &#xff08;1&#xff09; DCOM: 在安全描述符定义语言(SDDL)语法中的计算机访问限制 没有定义 DCOM: 在安全描述符定义语言(SDDL)语法中的计算机启动限制 没有定义 Microsoft 网络服…

无人机推流直播平台EasyDSS视频技术如何助力冬季森林防火

冬季天干物燥&#xff0c;大风天气频繁&#xff0c;是森林火灾的高发期。相比传统的人力巡查&#xff0c;无人机具有更高的灵敏度和准确性&#xff0c;尤其在夜间或浓雾天气中&#xff0c;依然能有效地监测潜在火源。 无人机可以提供高空视角和实时图像传输&#xff0c;帮助巡…

写SQL太麻烦?免费搭建 Text2SQL 应用,智能写 SQL | OceanBase AI 实践

自OceanBase 4.3.3版本推出以来&#xff0c;向量检索的能力受到了很多客户的关注&#xff0c;也纷纷表达希望OB能拓展更多 多模数据库大模型 的AI应用实践。 在上篇文章 &#x1f449; OceanBase LLM&#xff0c;免费构建你的专属 AI 助手 &#xff0c;我们介绍了如何去搭建一…

Halcon 机器视觉案例 之 药剂液面高度测量

第二篇 机器视觉案例 之 药剂液面高度测量 文章目录 第二篇 机器视觉案例 之 药剂液面高度测量1.案例要求2.实现思路2.1获得液面的位置&#xff1a;2.1.1 获得每支药剂的位置坐标2.1.2 根据药剂的横坐标设置卡尺工具助手找到每一个液面的位置 2.2 获得基准线的位置&#xff1a;…

使用k6进行MongoDB负载测试

1.安装环境 安装xk6-mongo扩展 ./xk6 build --with github.com/itsparser/xk6-mongo 2.安装MongoDB 参考Docker安装MongoDB服务-CSDN博客 连接成功后新建test数据库和sample集合 3.编写脚本 test_mongo.js import xk6_mongo from k6/x/mongo;const client xk6_mongo.new…

LabVIEW随机扫描成像系统

利用LabVIEW开发了一套随机扫描成像系统&#xff0c;利用硬件时钟实现声光偏转器&#xff08;AOD&#xff09;的频率控制与信号采集之间的高速时间同步。系统利用了高精度的时钟同步技术&#xff0c;确保了成像精度和重复性&#xff0c;从而有效提高了成像速度和质量。 项目背景…

29. 多线程编程

一、什么是线程 线程&#xff08;thread&#xff09;它们是同一个进程下执行的&#xff0c;并共享相同的下上文。线程包括开始、执行顺序和结束三部分。它有一个指令指针&#xff0c;用于记录当前运行的上下文。当其它线程运行时&#xff0c;它可以被抢占&#xff08;中断&…

精准采集整车信号:风丘混合动力汽车工况测试

一 背景 混合动力汽车是介于纯电动汽车与燃油汽车两者之间的一种新能源汽车。它既包含纯电动汽车无污染、启动快的优势&#xff0c;又拥有燃油车续航便捷、不受电池容量限制的特点。在当前环境下&#xff0c;混合动力汽车比纯电动汽车更符合目前的市场需求。 然而&#xff0c…

《军工记忆》第二季播出,科技创新铸国之重器

2019年8月1日晚20点&#xff0c;《军工记忆》第二季在央视纪录频道&#xff08;CCTV-9&#xff09;播出&#xff0c;第一集《第一颗氢弹》首当其冲&#xff0c;为我们生动描绘了氢弹研制过程的艰难岁月&#xff0c;重现中国军工事业的漫漫长路&#xff0c;科技创新铸国之重器。…

QT5.9.9+ARM交叉编译开发环境搭建【详细步骤】

文章目录 1.前言2.Linaro编译器下载2.qt-everywhere编译安装3.Linux下QT Creator安装4.交叉编译环境配置5.QTARM程序打包参考文献 1.前言 本文将以32位的ARM开发板为例&#xff0c;搭建基于Ubuntu 16.04虚拟机的QTARM开发环境&#xff0c;使用的软件如下&#xff1a; 序号软件…

深入解析 StarRocks 物化视图:全方位的查询改写机制

小编导读&#xff1a; 本文将重点介绍如何利用物化视图进行查询改写。文章将全面介绍物化视图的基本原理、关键特性、应用案例、使用场景、代码细节以及主流大数据产品的物化视图改写能力对比。 物化视图在 StarRocks 中扮演着至关重要的角色&#xff0c;它是进行数据建模和加速…

挑战一个月基本掌握C++(第五天)了解运算符,循环,判断

一 运算符 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 内置了丰富的运算符&#xff0c;并提供了以下类型的运算符&#xff1a; 算术运算符关系运算符逻辑运算符位运算符赋值运算符杂项运算符 1.1 算术运算符 假设变量 A 的值为 10&#xff0c;变量 B 的值为…

通过阿里云 Milvus 与 PAI 搭建高效的检索增强对话系统

背景介绍 阿里云向量检索服务Milvus版&#xff08;简称阿里云Milvus&#xff09;是一款云上全托管服务&#xff0c;确保了了与开源Milvus的100%兼容性&#xff0c;并支持无缝迁移。在开源版本的基础上增强了可扩展性&#xff0c;能提供大规模 AI 向量数据的相似性检索服务。相…

jQuery总结(思维导图+二维表+问题)

关于什么是jQuery&#xff1a;&#xff08;下面是菜鸟里的介绍&#xff09; jQuery 是一个 JavaScript 库。 jQuery 极大地简化了 JavaScript 编程。 jQuery 很容易学习。 而jQuery对我的感受就是&#xff0c;链式运用的很形象&#xff0c;隐式迭代还有一些兼容性强的优点&…

(14)CT137A- 动态数码管设计

&#xff08;1&#xff09;了解板卡原理图中数码管的特性&#xff1a;共阳极数码管&#xff0c;公共端连接了电源&#xff0c;FPGA IO口低电平有效&#xff0c;另外&#xff0c;可以看到位选端FPGA位选低电平时选通。 &#xff08;2&#xff09;刷新时间的设定&#xff1a;众所…

UG NX二次开发(C#)-如何设置UGOpen的UF_CAM_geom_type_e枚举类型

文章目录 1、前言2、UF_CAM_geom_type_e类型说明3、在C#的类型1、前言 UG NX二次开发提供的帮助文档,无论是c/c++、C#、Python、VB语言,其采用UFun函数时都是参考的UGOpen的帮助文档,即是:UGOPEN函数参考手册(nx6).CHM,后续的都没有怎么增加,这个在哪个版本中都适用。但…

内容与资讯API优质清单

作为开发者&#xff0c;拥有一套API合集是必不可少的。这个开发者必备的API合集汇集了各种实用的API资源&#xff0c;为你的开发工作提供了强大的支持&#xff01;无论你是在构建网站、开发应用还是进行数据分析&#xff0c;这个合集都能满足你的需求。你可以通过这些免费API获…

vue使用v-if和:class完成条件渲染

1.使用v-if 和v-else 完成主body和暂无数据两个<tbody>标签的条件渲染(注意与v-show效果的区别) 2.v-for完成列表渲染 3.:class完成分数标红的条件控制 删哪个就传哪个的id&#xff0c;基于这个id去过滤掉相同id的项&#xff0c;把剩下的项返回 <td><a click.p…