15_C语言 -构造类型
构造类型
数据类型
- 基本类型:
- 整型
- short / short int(2字节)
- 整型(默认) :int(4字节)
- 长整型:long / long int (8字节 (64位系统))
- 长长整型:long long / long long int(16字节)
- 浮点型
- 单精度:float(4字节)
- 双精度:double(8字节)
- 长双精度:long double(16字节(16位系统))
- 字符型:char(1字节)
- 整型
- 指针类型
- 数据类型*:
int*,char*,float*等
(8字节) - void*:任意数据类型的指针(万能指针)(8字节)
- 数据类型*:
- 空类型
- void:没有返回值或没有形参(不能定义变量)
- 自定义类型/构造类型
- 结构体类型:struct
- 共用体/联合体类型:union
- 枚举类型:enum
注意:整型和字符型分有符号signed和无符号unsigned
结构体
结构体的定义
-
定义:自定义数据类型的一种,关键字 struct,结构体类型的变量可以存储多个不同数据类型的数据。
-
定义格式:
struct 结构体 {数据类型1 成员名称; // 结构体中的变量叫做成员数据类型2 成员名称;··· }
注意:结构体中定义的变量,我们称之为成员变量
-
格式说明:
- 结构体名:合法的标识符,建议单词的首字母大写(所谓的结构体名,就是自定义类型的类型名称)
- 数据类型n:C语言支撑的所有类型(包括函数,函数在这里用函数指针表示)
- 成员的名称:合法的标识符,就是变量的命名标准
- 数据类型n成员名称n:类似于定义变量,定义了结构体中的成员
标识符:
说明:变量名、数组名、函数名、常量名、结构体名、共用体、枚举名等都是标识符
命名规则:
- 只能包含字母、数字、下划线
- 不能以数字开头
-
注意:
-
结构体在定义的时候,成员不能赋值
举例:
struct Cat {int age = 5; // 错误,结构体定义的时候,成员不能赋值double height; // 正确void (*run)(void); // 正确 }
-
常见的定义格式
-
方式1:常规定义(命名结构体,只定义类型) --推荐
struct Studebt {int num; // 学号char name[20]; // 姓名char sex; // 姓名int age; // 年龄char address[100]; // 家庭住址void (*info)(void); // 信息输出(函数指针) }
-
方式2:定义匿名结构体(常用于作为其他结构体的成员使用)
struct Dog {char *name; // 姓名 int age; // 年龄struct // 结构体{int year;int month;int day;} }
注意:定义匿名结构体的同时必须定义结构体变量,否则编译报错,结构体可以作为另一个结构体的成员。
总结:
- 结构体可以定义在局部位置,也可以定义在全局位置(用的比较多)。
- 全局位置的结构体名和局部位置的结构体名可以相同,就近原则(和普通变量的定义同理)
-
结构体类型的使用:
利用结构体类型定义变量,定义数组;结构体类型的使用于基本数据类型的使用类似。
-
-
结构体变量的定义
-
三种形式定义结构体变量
结构体变量也称为结构体的实例。
-
第一种
①先定义结构体(自定义数据类型)
②然后使用
struct 结构体名 变量名(实例);
举例:
// 先定义结构体(自定义数据类型) struct A {int a;char b; } // 后定义结构体变量(使用自定义数据类型) struct A x; struct A y;
-
第二种
①在定义结构体的同时,定义结构体变量
struct 结构体名 {数据类型1 数据成员1;··· }变量列表;
举例:
struct A {int a;int b; }x,y;struct A z;
此时定义了一个结构体A,x和y是这个结构体类型的变量。
-
第三种(不推荐)
在定义匿名结构体的同时,定义结构体变量
struct {int a;char b; }x,y;struct {int a;char b; } z;
此时定义了一个没有名字的结构体(匿名结构体);x,y是这个结构体类型的变量。
-
匿名结构体: -----弊大于利(尽量少用)
- 优点:少写一个结构体名称
- 缺点:只能使用一次,定义结构体类型的同时定义变量
- 作为其他结构体的成员使用。
-
定义结构体的同时,定义结构体变量初始化
struct Cat {int age;char color[20]; } cat;
-
结构体成员部分初始化时,大括号{}不能省略
-
结构体成员,没有默认值,是不确定的数
-
-
案例:
/** * 结构体变量的定义 */ #include <stdio.h> // 先定义结构体,再定义结构体变量 void fun1() {// 先定义结构体struct A{int a;char b;};// 再定义结构体变量struct A x;struct A y; } // 定义结构体的同时定义结构体变量 void fun2() {struct A{int a;char b;} x,y;struct A z; } // 定义匿名结构体的同时定义结构体变量 void fun3() {struct{int a;// 结构体成员char b;} x,y;// 结构体变量struct{int a;char b;} z; } int main() {fun1();fun2();fun3();return 0; }
结构体变量的使用
结构体变量访问结构体成员
-
结构体变量访问结构体成员
-
格式:
结构体变量名.成员名;
可以通过访问给成员赋值(存数据)
可以通过访问获取成员的值(取数据)
-
结构体变量未初始化,结构体的成员值随机(不确定)
-
-
结构体变量在定义时,可以初始化
-
建议用大括号表明数据 的范围
-
结构体成员初始化,可以部分初始化,部分初始化时一定要带
-
举例:
#include <stdio.h> #include <stdlib.h> //动态内存分配 #include <string.h> //字符串操作,内存操作 /*** 结构体变量的使用* */ // 定义全局的结构体(数据类型) struct Dog {char* name; //姓名int age; // 年龄char sex; // M:公,W:母void (*eat)(void); };void eat() {printf("狗狗在吃饭:\n"); } // 先定义在初始化 void fun1() {// 定义结构体变量struct Dog dog;// 给结构体变量赋值,其实就是给其他成员赋值dog.name = "旺财";dog.age = 5;dog.eat = eat;// 访问结构体变量,其实就是访问成员printf("%s,%d,%c\n", dog.name, dog.age, dog.sex);dog.eat(); }// 定义的同时初始化 void fun2() {// 定义结构体变量并初始化struct Dog dog = {"招财",23,'M'}; // 初始化时,保留大括号// 修改成员的值dog.name = "进宝";// 访问结构体变量,其实就是访问成员printf("%s,%d,%c\n", dog.name, dog.age, dog.sex); } int main(int argc,char *argv[]) {fun1();fun2();return 0; }
-
结构体数组的定义
-
什么时候需要结构体数组
比如:我们需要管理一个学生对象,只需要定义
struct Student gaochao;
假如:我们需要管理多个学生对象,此时就需要一个结构体数组
struct Student students[29];
-
三种形式定义结构体数组
-
第一种:先定义结构体类型,然后定义结构体变量,最后将变量存储到结构体数组
// 定义一个学生类型的结构体(定义数据类型) struct Student {char* name;int age;float scores[3]; }// 定义结构体实例(使用结构体定义变量) struct Student zhangsan = {"张三",21,{89,99,78}}; struct Student lisi = {"李四",22,{56,76,87}}; // 定义结构体数组 struct Student stus[3] = {zhangsan,lisi};
-
第二种:定义结构体类型,,然后定义结构体数组并初始化
// 定义一个学生类型的结构体 struct Student {int id;char* name;int age;float scores[3]; }// 定义结构体数组并初始化 struct Student stus[3] = {{1,"张三",21,{89,99,78}},// 注意:这里赋值的顺序需要跟成员在结构体中的顺序{2,"李四",22,{56,76,87}} };
-
第三种:定义结构体类型的同时定义结构体并完成初始化
// 定义一个学生类型的结构体 struct Student {int id; // 学生编号char* name; // 学生姓名int age; // 学生年龄float scores[3];// 学生三门课成绩 } stus[3] = {{1,"张三",21,{89,99,78}},// 注意:这里赋值的顺序需要跟成员在结构体中的顺序{2,"李四",22,{56,76,87}}
-
第四种:定义结构体类型的同时定义结构体数组,然后通过索引给结构体成员赋值
// 定义一个学生类型的结构体 struct Student {int id; // 学生编号char* name; // 学生姓名int age; // 学生年龄float scores[3];// 学生三门课成绩 } stus[3]; // 赋值 stus[0].id = 1; stus[0].name = "张三"; stus[0].age = 21; stus[0].scores[0] = 98;
-
小贴士:
结构体数组名访问结构体成员:
格式:结构体数组名 -> 成员名
案例:
#include <stdio.h> void info(char* str) {printf("%s\n",str); } void fun3() {// 定义一个学生类型的结构体struct Student{int id;char *name;int age;float scores[3];void (*info)(char*);};// 定义结构体实例并初始化struct Student stu1 = {1,"张三",21,{56,87,99}};struct Student stu2 = {2,"李四",22,{88,66,77}};stu1.info = info;stu2.info = info;// 定义结构体数组并初始化struct Student stus[] = {stu1,stu2};// 遍历结构体数组// 计算数组的大小int len = sizeof(stus) / sizeof(stus[0]);// 遍历for(int i = 0; i < len; i++){printf("%d,%s,%d,%p\n",stus[i].id,stus[i].name,stus[i].age,stus[i].scores);// 其是多个成员都是在访问同一个函数,此时没必要通过下标访问,改变实参就行了stus->info(stus[i].name);}printf("\n"); } int main(int argc,char *argv[]) {fun3();return 0; }
优先为指针遍历
#include <stdio.h> void info(char* str) {printf("%s\n",str); } void fun3() {// 定义一个学生类型的结构体struct Student{int id;char *name;int age;float scores[3];void (*info)(char*);};// 定义结构体实例并初始化struct Student stu1 = {1,"张三",21,{56,87,99}};struct Student stu2 = {2,"李四",22,{88,66,77}};stu1.info = info;stu2.info = info;// 定义结构体数组并初始化struct Student stus[] = {stu1,stu2};// 遍历结构体数组// 计算数组的大小int len = sizeof(stus) / sizeof(stus[0]);// 遍历struct Student *p = stus;for(; p < stus + len; p++){printf("%d,%s,%d,%p\n",p->id,p->name,p->age,p->scores);// 其是多个成员都是在访问同一个函数,此时没必要通过下标访问,改变实参就行了p->info(p->name);}printf("\n"); } int main(int argc,char *argv[]) {fun3();return 0; }
构造体类型
构造体数组
案例:
需求:对候选人得票的统计程序。设有3个候选人,每次输入一个得票的候选人名字,要求最后输出各人得票的结果。
#include <stdio.h>
#include <string.h>
/**
* 定义一个候选人构造体(对象)
*/
struct Person
{char name[20]; // 候选人名字int count; // 候选人票数
};
/**
* 定义候选人数组,并初始化
*/
struct Person persons[3] = {{"独孤长月",0},{"司空玄烨",0},{"诸葛蛋蛋",0}
};
int main(int argc,char *argv[])
{// 定义循环变量int i,j;// 创建一个char数组,用来存储控制台输入的候选人名字char leader_name[20];// 使用一个循环完成10次投票(模拟投票)for(i = 0; i < 10; i++){printf("请输入您要投票的候选人姓名:\n");scanf("%s",leader_name);// 给被投票的候选人+1票for(j = 0; j < 3; j++){// 判断两个字符串的结果是否相同if(strcmp(leader_name,persons[j].name)==0)persons[j].count++;}}printf("\n投票结果:\n");// 数组法//for(i = 0; i < 3; i++)//{// printf("%s:%d\n",persons[i].name,persons[i].count);//}// 指针法struct Person *p = persons;// p就是构造体指针for(;p < persons + 3;p++)printf("%s:%d\n",p->name,p->count);// 指针法for(i = 0; i < 3; i++){printf("%s:%d\n",(persons+i)->name,(persons+i)->count);}return 0;
}
构造体指针
-
定义:结构体类型的指针变量指向结构体变量或者数组的起始地址。
-
语法:
struct 结构体名 *指针变量列表;
-
举例:
struct Dog {char name[20];int age; }; struct Dog dog = {"富贵",5}; struct Dog *p = &dog;
构造体成员访问
-
结构体数组名访问结构体成员
-
格式:
结构体数组名 -> 成员名;
-
举例:
printf("%s:%d\n",persons->name,persons->count);
-
-
结构体成员访问符
-
.
:左侧是结构体变量(结构体对象/结构体实例),也可以叫做结构体对象访问成员符,右侧是结构体成员 -
->
:左侧是一个指针,也可以叫做结构体指针访问成员符,右侧是结构体成员 -
举例:
// 指针法 struct Person *p = persons;// p就是构造体指针 for(;p < persons + 3;p++)printf("%s:%d\n",p->name,p->count);
-
-
访问结构体成员有两种类型,三种方式:
-
类型1:通过结构体对象访问成员
struct Stu {int id;// 结构体成员char name[20]; } stu;// 结构体变量 // 访问成员 stu.name;
-
类型2:通过结构体指针访问成员
-
第1种:指针引用访问成员
struct Stu {int id;// 结构体成员char name[20]; } stu;// 结构体变量 struct Stu *p = &stu; // 指针引用访问成员 p -> name;
-
第2种:指针解引用间接访问成员
struct Stu {int id;// 结构体成员char name[20]; } stu;// 结构体变量 struct Stu *p = &stu; // 指针解引用访问成员 (*p).name;
-
-
-
结构体数组中元素的访问
struct Stu {int id;char name[20];float scores[3]; } stus[3] = {{1,"张三",{67,77,88}},// (stus+1){2,"李四",{90,99,98}},{3,"王五",{88,97,77}} }; // 取数据 -- 下标法 printf("%s,%.2f\n",stus[1].name,stus[1].scores[1]);// 李四,99 // 取数据 -- 指针法(->) printf("%s,%.2f\n",stus -> name,stus -> scores[2]);// 张三,88 printf("%s,%.2f\n",(stus+1) -> name,(stus+1) -> scores[2]);// 李四,98 printf("%s,%.2f\n",(*(stus+1)).name,(*(stus+1)).scores[2]);// 李四,98
小贴士:
结构体是自定义数据类型,它是数据类型,用法类似于基本类型的int;
结构体数组它是存放结构体对象的数组,类似于int数组存放int数据;
基本类型数组怎么用,结构体数组就怎么用—>可以遍历,可以作为形式参数,也可以做指针等;
-
结构体类型的使用案例
结构体可以作为函数的返回类型、形式参数。
代码:
#include <stdio.h> // 定义结构体 struct Cat {char *name;// 姓名int age;// 年龄char color[20];// 颜色 } // 1.结构体类型作为形式参数 void test1(struct Cat c); // 2.结构体类型作为形式参数,结构体类型作为返回值类型 struct Cat test2(struct Cat c); // 3.结构体数组作为形式参数 void test3(struct Cat cats[],int len); // 4.结构体数组作为形式参数,结构体指针作为返回值数据类型 struct Cat *test4(struct Cat cats[],int len);
测试:
int main() {// 定义结构体对象struct Cat cat = {"小黑",8,"baise"};// 结构体对象作为实际参数test1(cat);// 定义结构体类型对象struct Cat cat1 = {"小白",8,"heise"};// 调用函数并接收返回值struct Cat c1 = test2(cat1);// 通过返回值访问结构体对象的成员printf("%s==%d==%s\n",c1.name,c1.age,c1.color);// 定义结构体数组struct Cat cats[3] = {{"汤姆",16,"蓝色"},{"杰瑞",18,"褐色"},{"唐老鸭",19,"白色"}};// 结构体数组名作为实际参数test3(cats,3);// 定义结构体数组并初始化struct Cat cats1[3] = {{"汤姆",16,"蓝色"},{"杰瑞",18,"褐色"},{"唐老鸭",19,"白色"}};// 调用函数struct Cat *p = test4(cats1,3);struct Cat *w;// 通过指针运算遍历数组for(w = p; w < p + 3; w ++){// p[i][j] = *(p[i]+j) = *(*(p+i)+j) 三者等价// 通过结构体指针访问符访问结构体的成员printf("%s----%d----%s\n",w -> name,w -> age,w -> color);} }
构造体类型求大小
-
规则:字节对齐(默认,数据在内存中存储在其类型大小的整数倍上)
-
首先保证结构体中的成员存储在自身的对齐边界(类型大小的整数倍)
-
在满足1的条件下,最终大小要满足最大成员所占存储单元的整数倍。
-
-
为什么要使用字节对齐
节省内存,提高访问效率
-
在GNU标准中,可以在定义结构体时,指定对齐规则:
__attribute__((packed)); -- 结构体所占内存大小是所有成员所占内存大小之和 __attribute__((aligned(n))); -- 设置结构体占n个字节,如果n比默认值小,n不起作用;n必须是2的次方
-
案例:
#include <stdio.h> int main(int argc,char *argv[]) {struct Cat{char sex __attribute((aligned(2)));// 1 -- 2int id;// 4char name[20];// 20} __attribute__((packed)); // 结构体所占内存大小是所有成员所占内存大小之和printf("%ld\n",sizeof(struct Cat));// 默认字节对齐(28)/ 使用packed后(25)return 0; }
-
柔性数组
struct St {...char arr[0]; }
柔性数组不占有结构体的大小。
案例:
#include <stdio.h> int main(int argc,char *argv[]) {struct Cat{char sex __attribute((aligned(2)));// 1 -- 2int id; // 4char arr[0]; // 0 柔性数组不占用结构体的大小char name[20]; // 20} __attribute__((packed)); // 结构体所占内存大小是所有成员所占内存大小之和printf("%ld\n",sizeof(struct Cat));// 默认字节对齐(28)/ 使用packed后(25)/ 使用aligned之后(26)return 0; }
课堂练习
计算以下结构体的大小
#include <stdio.h>
// 定义测试结构体
struct TEST1
{char a;// 1 + 3int b; // 4
};
struct TEST1_1
{char a;// 1int b;// 4
}__attribute__((packed));// 取消字节对齐,取消之后,结构体数据类型大小就等于其所有成员的数据类型
之和struct TEST1_2{char a __attribute__((aligned(2)));// 2 + 2int b;// 4};
struct TEST2
{char a;// 1+1short c; // 2int b; // 4
};
struct TEST3
{int num;// 4char name[10];// 10char sex;// 1+1int age;// 4 + 4double score;// 8
};
struct TEST3_1
{int num;// 4char name[10];// 10char sex;// 1+1double score;// 8int age;// 4+4
};
struct TEST4
{int num;// 4short name[5];// 10char sex;// 1+1int age;// 4int scores[2];// 8
};
int main(int argc,char *argv[])
{// 创建结构体变量struct TEST1 test1;struct TEST2 test2;struct TEST3 test3;struct TEST3_1 test3_1;struct TEST4 test4;struct TEST1_1 test1_1;struct TEST1_2 test1_2;// 计算大小printf("%lu\n",sizeof(test1));// 8printf("%lu\n",sizeof(test2));// 8printf("%lu\n",sizeof(test3));// 32printf("%lu\n",sizeof(test3_1));// 28printf("%lu\n",sizeof(test4));// 28printf("%lu\n",sizeof(test1_1));// 5printf("%lu\n",sizeof(test1_2));// 8return 0;
}
快速计算结构体大小:
https://blog.csdn.net/weixin_72357342/article/details/131135555 https://blog.csdn.net/x2528238270/article/details/120798606
共用体**/**联合体类型
-
定义:使几个不同的变量占用同一段内存的结构。共用体按定义中需要存储空间最大的成员来分配存储单元,其他成员也是用该空间,他们的首地址是相同。
-
定义格式:
union 共用体名称 {数据类型 变量名; -- 共用体成员数据类型 变量名;... };
-
公用体的定义和结构体类似:
- 可以有名字,也可以匿名
- 共用体在定义时也可以定义公用体变量
- 共用体在定义时也可以初始化成员
- 共用体也可以作为形参和返回值类型使用
- 共用体也可以定义共用体变量
也就是说,结构体的语法,共用体都支持
-
注意:
-
共用体弊大于利,尽量少用,一般很少用;
-
共用体变量在某一时刻只能存一个数据,并且也只能取出一个数
-
共用体和结构体都是自定义数据类型,用法类似于基本数据类型
- 共用体可以是共用体的成员,也可以是结构体的成员
- 结构体可以是结构体的成员,也可以是共用体的成员
-
案例:
/** * 共用体 */ #include <stdio.h> // 定义共用体 union S {char a;float b;int c; };// 大小是4字节 // 共用体作为共用体的成员 union F {char a;union S s; // 4字节 };// 大小是4字节 // 共用体作为结构体的成员 struct G {int a;union S s; };// 大小是8字节 // 定义一个结构体 struct H {int a;char b; };// 大小是8字节 // 结构体作为结构体成员 struct I {int a; // 4int b; // 4struct H h; // 8 };// 大小是16字节 // 共用体作为结构体成员 struct J {int a;// 4char b;// 1 + 3union S s;// 4 };// 大小是12字节 void test1() {// 定义共用体类型union Stu{int num;char sex;double score;};// 定义匿名共用体:匿名共用体一般作为结构体成员或者其他共用体成员union{int a;char c;} c;printf("%lu,%lu\n",sizeof(union Stu),sizeof(c)); } void test2() {union C{int a;char b;};// 定义变量union C c;// 存数据c.a = 10;c.b = 'A';printf("%d---%d\n",c.a,c.b);// 取数据c.a += 5;printf("%d---%d\n",c.a,c.b);// 取数据union E{char *f;long a;int b;} e = {"hello world!"};printf("%s,%p---%ld,%p---%d\n",e.f,&(e.f),e.a,&(e.a),e.b); } int main() {test1();test2(); }
-
枚举类型
枚举类型
建议,如果定义不相干的常量,使用宏定义;如果需要定义一组相关的常量,使用枚举。以后正式开发,switch的case后访问的就是枚举。
-
定义 :
我们一般情况下,定义常量使用宏定义(#defne宏名称值),宏定义非常适合没有关联关系的常量;但是有时候我们可能需要对一组有关联关系的量进行定义,比如
==周一~周日、1月~12月、方向(上下左右中)等
,那么使用宏定义,就不是很清晰,这个时候就需要使用到枚举。枚举的存在就是多个将拥有多个关系的常量组合到一起,提高代码的可读性。
-
枚举类型 定义了一组常量,我们在开发中直接使用这些常量。(常用)
-
当然枚举类型也可以类似于结构体一样定义变量等操作。(不常用)
-
枚举常量有默认值,从0开始依次+1;我们可以在定义 时指定它的默认值,如果个别没有赋值,可以根据赋值依次+1推导。
-
特点:
定义了一组常量,类似于定义了多个自定义常量(宏定义)
提高了代码的可读性。
-
定义语法:
枚举类型名以后就可以定义该枚举类型的变量。
enum 枚举类型名 变量列表;
在定义枚举类型的同时定义该枚举类型的变量。
enum 枚举类型名{枚举元素列表} 变量列表;
直接定义枚举变量
enum {枚举元素列表} 变量列表;
案例:
#include <stdio.h>
void test1()
{// 定义一个枚举类型// 枚举类型名一般首字母大写,主要是根枚举变量区分enum Week{// 定义枚举元素,元素命名要符合标识符命名规则,同时采用大写字母+下划线方式命名SUN=10,MON,TUE,WED,THU,FRI,SAT};// 1.直接访问枚举元素printf("%d,%d,%d\n",SUN,WED,SAT);// 2.定义枚举类型的变量(先定义变量,后赋值)enum Week week;// 初始化week = TUE;// 一定是这个枚举类型中定义的元素printf("%d\n",week);// 3.定义枚举类型变量的同时赋值(定义变量和赋值同时进行)enum Week week1 = THU;printf("%d\n",week1);enum H{A,B,C // 多个元素使用逗号分隔} x,y;x = B;y = C;printf("x=%d,y=%d\n",x,y);// 1,2
}
void test2()
{// 定义枚举enum CaiQuan{SHI_TOU,JIAN_DAO,BU};printf("请输入0~2之间的整数:\n[0-石头,1-剪刀,2-布]\n");int number;scanf("%d",&number);switch(number){case SHI_TOU:printf("石头\n");break;case JIAN_DAO:printf("剪刀\n");break;case BU:printf("布\n");break;}
}
int main(int argc,char *argv[])
{test1();test2();return 0;
}
typedef
-
说明:给类型重命名,不会影响到类型本身
-
作用:给已有的类型起别名
-
格式:
typedef 已有类型名 新别名;
-
使用:
// 方式1:先定义结构体类型,在重命名 // 定义一个结构体 struct Student{int id;char *name;char sex;int age; };// 类型重命名 typedef struct Student Stu;// 定义结构体变量 struct Stu stu = {1,"张三",'w',21};// 方式2:定义结构体的同时重命名 typedef struct PersonInfo{int a;double b; }Per; // 结构体类型的别名,本质上还是数据类型// 定义变量 struct Per per = {2,5};
-
应用场景 :
- 数据类型复杂(结构体、共用体、枚举、结构体指针、无符号的长整型)时使用
- 为了跨平台兼容性,例如:
- size_t:类型重命名后的数据类型:
typedef unsigned long size_t;
- unit_16:类型重命名后的数据类型
- size_t:类型重命名后的数据类型:
-
案例:
//类型重命名
#include <stdio.h>
struct Student
{int age;char* name;double score;int arr[3];
};
typedef struct Student Stu_t;// 数据类型重命名
typedef Stu_t* pStu_t;// 结构体指针重命名
void test1()
{Stu_t s1 = {23, "zhangsan", 23.33, {11, 22, 33}};printf("%d, %s, %f, %d\n", s1.age, s1.name, s1.score, s1.arr[0]);//Stu_t *p = &s1;Stu_t* p;p = &s1;pStu_t p2;p2 = p;printf("%d, %s, %f, %d\n", p2->age, p2->name, p2->score, p2->arr[0]);
}
int main()
{test1();return 0;
}
相关文章:
15_C语言 -构造类型
构造类型 数据类型 基本类型: 整型 short / short int(2字节)整型(默认) :int(4字节)长整型:long / long int (8字节 (64位系统)&am…...
Python爬虫 - 豆瓣电影排行榜数据爬取、处理与存储
文章目录 前言一、使用版本二、需求分析1. 分析要爬取的内容1.1 分析要爬取的分类1.2 分析要爬取的单个电影的数据1.3 分析如何获取单个电影数据1.3.1 预览数据1.3.2 查看请求网址、方法及请求头信息1.3.3 查看请求参数 2. 数据用途2.1 统计分析2.2 探索性数据分析 (EDA)2.3 高…...
知识碎片-环境配置
1.添加-i 下载快: pip install onnxruntime-gpu==X.X.X -i https://pypi.tuna.tsinghua.edu.cn/simple 清华源 pip install xxx -i https://pypi.tuna.tsinghua.edu.cn/simple/ 阿里源 pip install xxx -i https://mirrors.aliyun.com/pypi/simple 中科大源 pip install xxx -…...
手机实时提取SIM卡打电话的信令声音-智能拨号器的SIP线路-双卡双待单通方案
手机实时提取SIM卡打电话的信令声音 --智能拨号器的SIP线路-双卡双待单通方案 一、前言 蓝牙电话的技术方案最初是从蓝牙耳机和车机蓝牙的使用领域延伸出来的技术方式。通过蓝牙的HFP协议,把手机通话的声音和通话事件状态提取出来进行复用和处理。但中国大陆现行…...
LangChain教程 - 表达式语言 (LCEL) -构建智能链
系列文章索引 LangChain教程 - 系列文章 LangChain提供了一种灵活且强大的表达式语言 (LangChain Expression Language, LCEL),用于创建复杂的逻辑链。通过将不同的可运行对象组合起来,LCEL可以实现顺序链、嵌套链、并行链、路由以及动态构建等高级功能…...
pytorch学习笔记汇总
一.tensor创建 1.张量的定义 张量在形式上就是多维数组,例如标量就是0维张量,向量就是一维张量,矩阵就是二维张量,而三维张量就可以想象RGB图片,每个channel是一个二维的矩阵,共有三个channel࿰…...
uniapp配置文字艺术字体风格
1.vue配置 App.vue中: <style>/*每个页面公共css *//* 全局字体风格 */font-face {font-family: gufengFont;src: url(./static/font/gufeng.ttf) format(truetype);font-weight: normal;font-style: normal;} </style>页面中: .text1 {f…...
江科大学习笔记之——HAL库点亮一个LED灯
HAL三步走:1.建工程。2.设配置。3.写代码 一.建立工程 HAL库写法 点击FinIsh 2.配置时钟 2 、设置配置参数 把模块.C.h单独设置文件 生产代码 三写代码 控制GPIO就三步 1.RCC时钟使能 2.结构体配置GPIO寄存器 3.控制GPIO值 上面的步骤已经把前两步的配置完成了接下…...
java web项目软件自动生成使用初体验-帅帅软件生成平台ASoft
软件默认 登陆账号 admin 密码 123456 一、软件使用简介说 AI软件自动生成越来越成熟,但AI生成的软件代码只是片段化的,不成体系。有没有一款可以10-30分钟自动生成JAVA WEB休系的软件?我也找了好久,终于找到了,开发…...
损失函数-二分类和多分类
二分类和多分类的损失函数 二分类 损失函数 L ( y , y ^ ) − ( y l o g ( y ^ ) ) ( 1 − y ) l o g ( 1 − y ^ ) L(y,\hat{y}) -(ylog(\hat{y})) (1-y)log(1-\hat{y}) L(y,y^)−(ylog(y^))(1−y)log(1−y^) 其中真实标签表示为y(取值为 0 或 1&#…...
Springboot:后端接收数组形式参数
1、接收端写法 PermissionAnnotation(permissionName "",isCheckToken true)PostMapping("/batchDeleteByIds")public ReturnBean webPageSelf( NotNull(message "请选择要删除的单据!") Long[] ids) {for (Long string : ids) {l…...
CSS系列(46)-- Color Functions详解
前端技术探索系列:CSS Color Functions详解 🎨 致读者:探索颜色函数的艺术 👋 前端开发者们, 今天我们将深入探讨 CSS Color Functions,这个强大的颜色处理特性。 基础函数 🚀 颜色空间 /…...
MySQL数据库误删恢复_mysql 数据 误删
2、BigLog日志相关 2.1、检查biglog状态是否开启 声明: 当前为mysql版本5.7 当前为mysql版本5.7****当前为mysql版本5.7 2.1.1、Navicat工具执行 SHOW VARIABLES LIKE LOG_BIN%;OFF 是未开启状态,如果不是ON 开启状态需要开启为ON。{默认情况下就是关闭状态} 2.…...
ModiLeo交易平台:引领数字货币交易新未来
在当今数字化高速发展的时代,数字货币作为一种新兴的金融资产形式,正逐渐改变着全球金融格局。而此刻,由印度 ModiLeo 实验室联合全球顶级投行共同打造的全球领先的一站式数字货币交易平台——ModiLeo 即将上线,这无疑是数字货币领…...
57.插入区间 python
插入区间 题目题目描述示例 1:示例 2:提示: 题解解题思路python实现代码解释提交结果 题目 题目描述 给你一个 无重叠的 ,按照区间起始端点排序的区间列表 intervals,其中 intervals[i] [starti, endi] 表示第 i 个…...
使用WebRTC进行视频通信
一、WebRTC技术简介 什么是WebRTC? 是一种支持浏览器之间实时音频、视频和数据传输的开放源代码项目。它允许开发者在不需要任何第三方插件或软件的情况下实现点对点的实时通信。WebRTC已经成为现代Web应用中的关键技术,为开发者提供了强大的工具和API…...
详细讲解axios封装与api接口封装管理
一、axios封装 axios是基于promise的http客户端,用于浏览器和nodejs发送http请求 ,对它进行封装主要是为了统一管理请求配置和处理请求和响应的通用逻辑等。以下是常用的封装逻辑和要点 1:引入axios相关依赖 首先引用项目中的axios库&…...
likeAdmin架构部署(踩坑后的部署流程
1、gitee下载 https://gitee.com/likeadmin/likeadmin_java.git 自己克隆 2、项目注意 Maven:>3.8 ❤️.9 (最好不要3.9已经试过失败 node :node14 (不能是18 已经测试过包打不上去使用14的换源即可 JDK:JDK8 node 需要换源 npm c…...
算法-回文数判断
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数 是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 例如,121 是回文,…...
力扣-数据结构-7【算法学习day.78】
前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?建议灵神的题单和代码随想录)和记录自己的学习过程,我的解析也不会做的非常详细,只会提供思路和一些关…...
计算机组成原理的学习笔记(8)-- 指令系统·其一 指令的组成以及数据寻址方式/RISK和CISK
学习笔记 前言 本文主要是对于b站尚硅谷的计算机组成原理的学习笔记,仅用于学习交流。 1. 指令 1.1 组成 操作码(Opcode):指指令中执行特定操作的部分。地址码:指令中用于指定操作数位置的部分。 1.2 扩展操作…...
Hive刷分区MSCK
一、MSCK刷分区 我们平时通常是通过alter table add partition方式增加Hive的分区的,但有时候会通过HDFS put/cp命令或flink、flum程序往表目录下拷贝分区目录,如果目录多,需要执行多条alter语句,非常麻烦。Hive提供了一个"…...
2024年12月HarmonyOS应用开发者基础认证全新题库
注意事项:切记在考试之外的设备上打开题库进行搜索,防止切屏三次考试自动结束,题目是乱序,每次考试,选项的顺序都不同,如果有两台电脑设备建议一台打开题库一台考试,如果只有一台电脑设备建议手…...
集成方案 | Docusign + 蓝凌 EKP,打造一站式合同管理平台,实现无缝协作!
本文将详细介绍 Docusign 与蓝凌 EKP 的集成步骤及其效果,并通过实际应用场景来展示 Docusign 的强大集成能力,以证明 Docusign 集成功能的高效性和实用性。 在当今数字化办公环境中,企业对于提高工作效率和提升用户体验的需求日益迫切。蓝凌…...
centos7 免安装mysql5.7及配置(支持多个mysql)
一) 下载免安装包: mysql下载地址: https://dev.mysql.com/downloads/mysql/下载时,选择以前5.7版本: image 下载第一个TAR压缩包: image 二) 定义安装路径并解压安装包 1、假设需要把MySQL放到 /usr/local…...
【若依框架】代码生成详细教程,15分钟搭建Springboot+Vue3前后端分离项目,基于Mysql8数据库和Redis5,管理后台前端基于Vue3和Element Plus,开发小程序数据后台
今天我们来借助若依来快速的搭建一个基于springboot的Java管理后台,后台网页使用vue3和 Element Plus来快速搭建。这里我们可以借助若依自动生成Java和vue3代码,这就是若依的强大之处,即便你不会Java和vue开发,只要跟着石头哥也可…...
什么是容器?
什么是容器? 容器是一种虚拟化技术,用于将应用程序及其所有依赖项打包在一起,以便在不同的计算环境中进行移植和运行。容器提供了一种隔离的运行环境,使不同应用程序能够在独立的文件系统、网络和进程空间等独立运行环境中运行&a…...
苍穹外卖——准备工作
模块介绍 后端的工程基于Maven进行项目构建,并且进行分模块开发,我们创建四个模块: sky-take-out:maven父工程,统一管理依赖版本,聚合其他子模块sky-common:子模块,存放公共类&…...
LLMs之o3:《Deliberative Alignment: Reasoning Enables Safer Language Models》翻译与解读
LLMs之o3:《Deliberative Alignment: Reasoning Enables Safer Language Models》翻译与解读 导读:2024年12月,这篇论文提出了一种名为“审慎式对齐 (Deliberative Alignment)”的新方法,旨在提高大型语言模型 (LLM) 的安全性。论…...
百度二面,MySQL 怎么做权重搜索?
考虑这样一个搜索需求,有一个 MySQL 表,表中很多个列存放着不同的内容,希望用户通过关键词进行搜索的时候,能够模糊匹配多个列,比如有 t1 列、t2 列、t3 列,同时还希望 t1 列的匹配权重最高,t3 …...
PHP:IntelliJ IDEA 配置 PHP 开发环境及导入PHP项目
在创建PHP项目之前我们需要安装PHP插件,安装步骤如下:Windows:IntelliJ IDEA Ultimate 安装 PHP 插件-CSDN博客 1、导入已有PHP项目,导入之后选择,File > Setting 选择对应CLL Interpreter,如果没有操作…...
国产数据库TiDB从入门到放弃教程
国家层面战略,安全的角度,硬件、软件国产化是趋势,鸿蒙电脑操作系统、鸿蒙手机操作系统…数据库也会慢慢国产化,国产数据库TiDB用起来比OceanBase丝滑,本身没有那么重。 从入门到放弃 1. 介绍1.1 TiDB 的主要特点1.2 T…...
Android 自定义控件
目录 Android 自定义控件 一、什么是自定义控件 二、创建自定义控件的常见方式 2.1继承现有控件(如 Button、TextView 等) 2.2直接继承 View 类 2.3组合控件 三、自定义控件的基本步骤 3.1创建一个继承自 View 或现有控件的类 3.2重写 onDraw()…...
学习笔记 --C#基础其他知识点(同步和异步)
C#中的同步和异步《一》 以下理解借鉴博客:借鉴博客地址1 异步编程(Asynchronous) 允许任务在后台执行,而不会阻塞调用线程。C#使用async和await关键字 async Task AsynchronousMethod() {// 等待异步操作完成await Task.Dela…...
药片缺陷检测数据集,8625张图片,使用YOLO,PASICAL VOC XML,COCO JSON格式标注,可识别药品是否有缺陷,是否完整
药片缺陷检测数据集,8625张图片,使用YOLO,PASICAL VOC XML,COCO JSON格式标注,可识别药品是否有缺陷,是否完整 有缺陷的标注信息: 无缺陷的标注信息 数据集下载: yolov11:https://d…...
Hive如何创建自定义函数(UDF)?
目录 1 自定义UDF函数基础 2 自定义UDF函数案例 3 创建临时函数 4 创建永久函数 1 自定义UDF函数基础 1. 内置函数:Hive 自带了一些函数...
深入理解MVCC:快照读与当前读的原理及实践
一、引言 MVCC是数据库系统中一种常见的并发控制技术,它允许多个事务同时对同一数据进行读取和修改,而不会相互干扰。在MVCC中,数据行存在多个版本,每个版本对应一个事务。本文将重点讨论MVCC中的两种读取方式:快照读…...
活动预告 |【Part1】Microsoft Azure 在线技术公开课:数据基础知识
课程介绍 参加“Azure 在线技术公开课:数据基础知识”活动,了解有关云环境和数据服务中核心数据库概念的基础知识。通过本次免费的介绍性活动,你将提升在关系数据、非关系数据、大数据和分析方面的技能。 活动时间:01 月 07 日…...
小程序笔记
1.小程序全局配置app.json {"pages":["pages/index/index","pages/logs/logs"],"window":{"backgroundTextStyle":"light","navigationBarBackgroundColor": "#fff","navigationBarTit…...
linux安装nginxs报错:openssl not found
系统: linux 版本:centOS7 nginx版本:nginx-1.20.2 linux安装nginx时 执行下面命令时报错: ./configure --with-http_stub_status_module --with-http_ssl_module --prefix/usr/local/nginxchecking for OpenSSL library ... not …...
Vite内网ip访问,两种配置方式和修改端口号教程
目录 问题 两种解决方式 结果 总结 preview.host preview.port 问题 使用vite运行项目的时候,控制台会只出现127.0.0.1(localhost)本地地址访问项目。不可以通过公司内网ip访问,其他团队成员无法访问,这是因为没…...
地理数据库Telepg面试内容整理-如何在高并发情况下保证GIS服务的高可用性?
在高并发情况下,保证 GIS 服务的高可用性是一个重要的挑战,尤其是当空间数据量巨大、请求频繁时。为了确保 GIS 服务的高可用性和稳定性,需要考虑以下几个方面: 分布式架构设计 分布式架构通过将工作负载分配到多个服务器上,能够大大提高服务的可用性和扩展性。通过设计高…...
ES中查询中参数的解析
目录 query中参数match参数match_allmatch:匹配指定参数match_phrase query中其他的参数query_stringprefix前缀查询:wildcard通配符查询:range范围查询:fuzzy 查询: 组合查询bool参数mustmust_notshould条件 其他参数 query中参数 词条查询term:它仅匹配在给定字段…...
【Java 数据结构】合并两个有序链表
🔥博客主页🔥:【 坊钰_CSDN博客 】 欢迎各位点赞👍评论✍收藏⭐ 目录 1. 题目 2. 解析 3. 代码实现 4. 小结 1. 题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示…...
OpenCV-Python实战(8)——图像变换
一、缩放 cv2.resize() img cv2.resize(src*,dsize*,fx*,fy*,interpolation*) img:目标图像。 src:原始图像。 dsize:(width,height)图像大小。 fx、fy:可选参数,水平/垂直方向…...
深入浅出:从入门到精通大模型Prompt、SFT、RAG、Infer、Deploy、Agent
阅读原文 渐入佳境 我们都知道,通过编写一个提示词(prompt),我们可以引导大模型生成回答,从而开启愉快的人工智能对话,比如让模型介绍一下卡皮巴拉。上边简图描述了这个过程,我们拆成两部分 pr…...
GXUOJ-算法-第二次作业(矩阵连乘、最长公共子序列、0-1背包问题、带权区间调度)
1.矩阵连(链)乘 问题描述 GXUOJ | 矩阵连乘 代码解答 #include<bits/stdc.h> using namespace std;const int N50; int m[N][N]; int p[N]; int n;int main(){cin>>n;//m[i][j] 存储的是从第 i 个矩阵到第 j 个矩阵这一段矩阵链相乘的最小…...
生态碳汇涡度相关监测与通量数据分析实践技术应用
1.以涡度通量塔的高频观测数据为例,基于MATLAB开展上机操作: 2.涡度通量观测基本概况:观测技术方法、数据获取与预处理等 3.涡度通量数据质量控制:通量数据异常值识别与剔除等 4.涡度通量数据缺失插补:结合气象数据…...
使用OpenAI、LangChain、MongoDB构建一个AI agent
LangChain真是好起来了。24年中的时候用LangChain V2差点把我气死,现在V3用起来开始真香了~ 像 ChatGPT、Gemini 和 Claude 这样的大模型已成为企业必不可少的工具。如今,几乎每家公司都希望根据自己的需求或客户群体,开发一款定制化的AI Age…...
如何在 Ubuntu 22.04 上安装并开始使用 RabbitMQ
简介 消息代理是中间应用程序,在不同服务之间提供可靠和稳定的通信方面发挥着关键作用。它们可以将传入的请求存储在队列中,并逐个提供给接收服务。通过以这种方式解耦服务,你可以使其更具可扩展性和性能。 RabbitMQ 是一种流行的开源消息代…...