9.构造类型
一、结构体
1.产生及意义
2.类型的描述
使用格式:结构体成员是不占用内存空间的,类比于int
属于类型范畴。
struct [结构体名]
{
//成员间的数据类型可以不同
数据类型 成员1;
数据类型 成员2;
······
}[one or more struct variables];
3.嵌套描述
struct data
{
int year;
int month;
int day;
};
struct info
{
int id;
char str[STRSIZE] address;
struct data birth;
char level;
}
上述 struct data data; 可转换为:
struct info
{
int id;
char str[STRSIZE] address;
struct data
{
int year;
int month;
int day;
}birth; //注意结构体定义只是一个类型,因此需要定义变量 birth
char level;
}
嵌套结构体引用:定义时初始化变量使用嵌套定义:
struct info a = {100001,"hello0",{2022,9,28},'A'};
部分引用:struct info a = (.id = 10001,.birth.day = 28)
;
如果引用结构体a
的info
中的month
:a.birth.month
4.定义变量(变量、数组、指针),初始化及成员引用
成员引用1:变量名.成员名
示例代码:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 struct sim
5 {
6 int i;
7 float f;
8 char ch;
9 };
10
11 int main()
12 {
13 // TYPE NAME = VALUE
14 struct sim a = {23,23.22222,'a'}; //initiallization
15 a.i = 45; //variable references
16
17 printf("%d %f %c\n",a.i,a.f,a.ch);
18
19 exit(0);
20 }
输出结果:
jxs@jxs-ubuntu:~/Desktop/c language/creat_type$ ./struct
45 23.222219 a
成员引用2:指针->成员名
成员引用3:(*指针).成员名
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #define N 128
5
6 struct birth
7 {
8 int year;
9 int month;
10 int day;
11 };
12
13 struct info
14 {
15 int id;
16 struct birth bir;
17 char name[N];
18 float math;
19 float chinese;
20 };
21
22 int main()
23 {
24 struct info stu_arr[2] = {{10001,{2022,9,28},"Alan",97.99,98},{10002,{2022,9,28},"Jack",96,56}};
25 struct info *p = &stu_arr[0];
26 struct info stu = {10001,{2022,9,28},"Bobo",97.99,98};
27 struct info *q = &stu; //need &!
28 int i;
29
30 for(i = 0; i < 2; i++, p++) // p + 1 表示跳过一个结构体的大小
31 {
32 printf("%d %d-%d-%d %s %f %f\n",p -> id, p -> bir.year, p -> bir.month, p -> bir.day, p -> name, p -> math, p -> chinese);
33 }
34 printf("%d %d-%d-%d %s %f %f\n",(*q).id, (*q).bir.year, (*q).bir.month, (*q).bir.day, (*q).name, (*q).math, (*q).chinese);
35
36 exit(0);
37 }
输出结果:
jxs@jxs-ubuntu:~/Desktop/c language/creat_type$ ./struct1
10001 2022-9-28 Alan 97.989998 98.000000
10002 2022-9-28 Jack 96.000000 56.000000
10001 2022-9-28 Bobo 97.989998 98.000000
5.占用内存空间大小
示例代码:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 //#define N 128
5
6 struct birth
7 {
8 char ch;
9 int year;
10 int month;
11 int day;
12
13 };
14
15 int main()
16 {
17 struct birth bir = {'a',2022,9,28};
18 struct birth *p = &bir;
19 printf("bir.ch --> %p\nbir.year --> %p\nbir.month --> %p\nbir.day --> %p\n", &bir.ch, &bir.year, &bir.month, &bir.day);
20 printf("size of bir : %ld\n",sizeof(bir));
21 printf("size of bir : %ld\n",sizeof(p));
22
23 exit(0);
24 }
输出结果:
jxs@jxs-ubuntu:~/Desktop/c language/creat_type$ ./structsize
bir.ch --> 0x7ffd83def2d0
bir.year --> 0x7ffd83def2d4
bir.month --> 0x7ffd83def2d8
bir.day --> 0x7ffd83def2dc
size of bir : 16
size of bir : 8
结构体所占用空间大小按照类型来计算时,应该为 1 + 4 + 4 + 4 = 13,但该结构体实际占用的内存为16。原因在于编译器的地址对齐!
使用下面这种方式就会等于13
6 struct birth
7 {
8 char ch;
9 int year;
10 int month;
11 int day;
12
13 }__attribute__((packed));
bir.ch --> 0x7ffc9c4a4e1b
bir.year --> 0x7ffc9c4a4e1c
bir.month --> 0x7ffc9c4a4e20
bir.day --> 0x7ffc9c4a4e24
size of bir : 13
size of bir : 8
6.函数传参(值传递、地址传递)
使用值传递会增大形参的空间开销,使用指针则可以减少空间开销。
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 //#define N 128
5
6 struct birth
7 {
8 char ch;
9 int year;
10 int month;
11 int day;
12
13 };
14
15 void func1(struct birth *i)
16 {
17 printf("size of point : %ld\n",sizeof(i));
18 }
19
20 void func2(struct birth i)
21 {
22 printf("size of struct : %ld\n",sizeof(i));
23
24 }
25
26 int main()
27 {
28 struct birth a;
29 struct birth *p = &a;
30
31 func2(a);
32 func1(p);
32 func1(p);
33
34 exit(0);
35 }
jxs@jxs-ubuntu:~/Desktop/c language/creat_type$ ./structfunc
size of struct : 16
size of point : 8 //因此一般使用指针进行传参
-
微型学生管理系统
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #define NAMESIZE 128
6
7 struct info
8 {
9 int id;
10 char name[NAMESIZE];
11 int math;
12 int chinese;
13 };
14
15 void menu(void)
16 {
17 printf("\n1.set_info\n2.rename\n3.show_info\n\n");
18 printf("Please input num to choose the function :");
19 }
20
21
22 void set_info(struct info *a)
23 {
24 printf("Please input info [id name math chinese]: \n");
25 scanf("%d%s%d%d",&(*a).id,(*a).name,&(*a).math,&(*a).chinese);
//scanf("%d%s%d%d", &a->id, a->name, &a->math, &a->chinese);
26 }
/*
void set_info(struct info *a)
{
printf("Please input info [id name math chinese]: \n");
//scanf("%d%s%d%d",&(*a).id,(*a).name,&(*a).math,&(*a).chinese);
a->name = malloc(NAMEMAX); //Assign NAMEMAX bytes for name
if(a->name == NULL)
exit(1);
scanf("%d%s%d%d",&a->id,a->name,&a->math,&a->chinese);
free(a->name);
}
*/
27
28 void change_name(struct info *p, const char *newname)
29 {
30 strcpy(p->name,newname);
31 }
32
33 void show_info(struct info *p)
34 {
35 printf("id\tname\tmath\tchinese\n");
36 printf("%d\t%s\t%d\t%d\n",p->id,p->name,p->math,p->chinese);
37 }
38
39 int main()
40 {
41 struct info stu;
42 struct info *q = &stu;
43 int num;
44 int ret;
45 char newname[NAMESIZE];
46 do
47 {
48 menu();
49 scanf("%d",&num);
50 if(num != 1 && num != 2 && num != 3)
51 printf("Please input the right value!\n\n");
52
53 switch(num)
54 {
55 case 1:
56 set_info(&stu);
57 break;
58 case 2:
59 printf("Please input a new name :");
60 scanf("%s",newname);
61 change_name(&stu,newname);
62 break;
63 case 3:
64 show_info(&stu);
65 break;
66 default:
67 break;
68 }
69
70 }while(1);
71
72 exit(0);
73 }
执行结果:
1.set_info
2.rename
3.show_info
Please input num to choose the function :3
id name math chinese
2021170116 liming 98 56
二、共用体
1.产生及意义
共用体是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。可以定义一个带有多成员的共用体,但是任何时候只有一个成员带有值,共用体提供了一种使用相同内存位置的有效方式。
共用体与结构体不同之处在于,前者由于是多个成员共用一个内存位置,因此成员的值只能择其一。结构体所有的成员都可以有各自的值。
2.类型的描述
union [共用体名]
{
数据类型 成员名1;
数据类型 成员名2;
······
}[one or more union variables];
3.嵌套定义
与结构体类似,无特殊之处。并且可以与结构体进行嵌套。
计算32位无符号数高十六位与低十六位相加的和。
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4
5 int main()
6 {
7 uint32_t i = 0x11223344;
8 printf("%x\n",(i >> 16) + i & 0xFFFF);
9
10
11 exit(0);
12 }
使用共用体:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4
5 union
6 {
7 struct
8 {
9 uint16_t i;
10 uint16_t j;
11 }b;
12 uint32_t k;
13 }a;
14
15 int main()
16 {
17 a.k = 0x11223355;
18 printf("%x + %x = %x\n", a.b.i, a.b.j, a.b.i + a.b.j);
19 printf("a.k: %p\na.b.i: %p\na.b.j: %p\n", &a.k, &a.b.i, &a.b.j);
20 printf("size of union a : %ld\n",sizeof(a));
21
22 exit(0);
23 }
jxs@jxs-ubuntu:~/Desktop/c language/creat_type$ ./uint1
3355 + 1122 = 4477
a.k: 0x556a58f3a014
a.b.i: 0x556a58f3a014
a.b.j: 0x556a58f3a016
size of union a : 4
union
中的内存分配:
"高尾端(big-endian)"与"低尾端(little-endian)" (数据地位由左到右依次降低)
如果将一个数视为一个字符串,如
11223344
视为"11223344"
,末尾是\0
,11
22
33
44
各占用一个存储单位(1个字节),那么其尾端是44
。尾端的高低定义取决于尾端放在高地址还是低地址。
//大端:数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中
//小端:数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中
int a = 0x123;
//在内存中,int类型有4个字节,2个二进制数为一个字节
//所以有8个十六进制进制数
//补齐0是 0x 00 00 01 23(23是尾端)
// 数据高位------(降低)-------数据地位
// 内存中:
// 大端 00 00 01 23
// 小端 23 01 00 00
// 低地址-----------------高地址
4.定义变量(变量、数组、指针),初始化以及成员引用
5.占用内存大小
共用体占用的内存应足够存储占用内存最大的变量。
6.函数传参(值传递、地址传递)
7.位域
三、枚举
使用格式:enum 枚举名 {枚举元素1,枚举元素2,……};
使用方式类似于#define
,例如:
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7
//等同于:
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN //成员皆变量
};
//枚举变量定义:
1.先定义枚举类型,再定义枚举变量
enum Day
{
MON, TUE, WED, THU, FRI, SAT, SUN //注意没有分号`;`
};
enum day;
2.定义枚举类型同时定义枚举变量
enum Day
{
MON, TUE, WED, THU, FRI, SAT, SUN
}day;
3.省略枚举名,直接定义枚举变量名
enum
{
MON, TUE, WED, THU, FRI, SAT, SUN
}day;
第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个的基础上加1.不论是中间的哪一个值被赋值,其后未被赋值的成员的值仍满足上述规定。
示例代码:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 enum DAY
5 {
6 MON = 1,TUS,THR,WES,FRI,SAT,SUN //MON之后的变量依次加一
7 };
8
9 int main()
10 {
11 enum DAY day2 = TUS;
12 enum DAY day5 = FRI;
13
14 printf("day2 = %d and size of day2 = %ld\n",day2,sizeof(day2));
15 printf("day5 = %d and size of day5 = %ld\n",day5,sizeof(day5));
16
17 exit(0);
18 }
输出结果:
day2 = 2 and size of day2 = 4
day5 = 5 and size of day5 = 4
使用场景:比如判断服务器的状态让其执行相应的任务。
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <time.h>
4
5 struct job
6 {
7 int id;
8 int state;
9 time_t start,end;
10 };
11
12 enum
13 {
14 STATE_RUNNING = 1,
15 STATE_CANCELED,
16 STATE_OVER
17 };
18
19 int main()
20 {
21 struct job job1;
22
23 //obtain the assignment state
24 switch(job1.state)
25 {
26 case STATE_RUNNING: //这里未定义enum 变量,但可以直接使用该变量的值,就相当于宏定义
27 printf("This job is running!\n");
28 break;
29
30 case STATE_CANCELED:
31 printf("This job is dennied!\n");
32 break;
33
34 case STATE_OVER:
35 printf("This job is over!\n");
36 break;
37
38 default:
39 abort(); //异常进程终止
40
41 }
42
43 exit(0);
44 }
45
-
typedef:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 typedef int INT; //typedef 数据类型(包含构造类型) 类型别名
5 //#define INT int //#define [marco name] [marco body] :replace all the 'INT' to 'int'
6
7 //difference:
8 /*1.typedef int * INT
9 *def: INT p, q; --> int *p, int *q;
10 *
11 *
12 *2.#define INT int*
13 *def: INT p, q; --> int *p, int q;
14 */
15
16 /*detailes in typedef
17 * 1.arr: typedef int ARR[6] (int [6] --> ARR);
18 * ARR a; --> int a[6];
19 *
20 *
21 * 2.struct
22 * struct node_st
23 * {
24 * int i;
25 * float j;
26 * };
27 *
28 * 1)typedef node_st NODE; --> struct node_st NODE;
29 * NODE a; --> struct node_st a;
30 * NODE *p; --> struct node_st *p;
31 *
32 * 2)typedef node_st *NODEP; --> struct node_st *NODEP;
33 * NODEP p; --> struct node_st *p;
34 *
35 * 3)typedef struct
36 * {
37 * int i;
38 * float j;
39 * }NODE,*NODEP; equal to def of 1) and 2).
40 *
41 *
42 * 3.functions:
43 * 1)typedef int FUNC(int); --> int FUNC(int);
44 * FUNC f; --> int f(int);
45 *
46 * 2)typedef int *FUNCP(int); --> int *FUNCP(int);
47 * FUNCP p; --> int *p(int);
48 *
49 * 3)typedef int *(*FUNCPP)(int); --> int *(*FUNCPP)(int);
50 * FUNCPP q; --> int *(*q)(int);
51 */
52
53
54
55 int main()
56 {
57 INT i = 4;
58 printf("i = %d\n",i);
59
60 exit(0);
61 }
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #define NAMEMAX 128
6
7 typedef struct info
8 {
9 int id;
10 char *name;
11 int math;
12 int chinese;
13 }STU;
14
15 void menu(void)
16 {
17 printf("\n1.set_info\n2.rename\n3.show_info\n4.exit\n\n");
18 printf("Please input num to choose the function :");
19 }
20
21
22 void set_info(STU *a)
23 {
24 printf("Please input info [id name math chinese]: \n");
25 //scanf("%d%s%d%d",&(*a).id,(*a).name,&(*a).math,&(*a).chinese);
26 a->name = malloc(NAMEMAX); //Assign NAMEMAX bytes for name
27 if(a->name == NULL)
28 exit(1);
29 scanf("%d%s%d%d",&a->id,a->name,&a->math,&a->chinese);
30 free(a->name);
31 }
32
33 void change_name(STU *p, const char *newname)
34 {
35 strcpy(p->name,newname);
36 }
37
38 void show_info(STU *p)
39 {
40 printf("id\tname\tmath\tchinese\n");
41 printf("%d\t%s\t%d\t%d\n",p->id,p->name,p->math,p->chinese);
42 }
43
44 int main()
45 {
46 STU stu;
47 STU *q = &stu;
48 int num;
49 int ret;
50 char newname[NAMEMAX];
51 do
52 {
53 menu();
54 scanf("%d",&num);
55 if(num != 1 && num != 2 && num != 3 && num != 4)
56 printf("Please input the right value!\n\n");
57
58 switch(num)
59 {
60 case 1:
61 set_info(&stu);
62 break;
63 case 2:
64 printf("Please input a new name :");
65 scanf("%s",newname);
66 change_name(&stu,newname);
67 break;
68 case 3:
69 show_info(&stu);
70 break;
71 case 4:
72 exit(0);
73 default:
74 break;
75 }
76
77 }while(1);
78
79 exit(0);
80 }
本文来自博客园,作者:假行僧me,转载请注明原文链接:https://www.cnblogs.com/jxsme/p/17514692.html