自定义类型:结构体
结构体
C语言中提供了内置类型如char、int等,生活中形容一个人的身高可以使用double,但是当要描述一个人,很显然只有身高是不足以描述这个人的,描述一个人需要身高、体重、名字、胖瘦等,为了解决此问题,C语言增加了自定义的数据类型结构体,能让程序员创造适合的类型。
正常结构体
结构体内是一些值的集合,这些值称为成员变量,每个成员变量的类型可以是不同的,可以是整型、浮点型、指针、数组甚至是结构体。
结构体声明:
注意:结构体最后的分号不能丢。
struct tag//结构体类型
{
member-list;//结构体成员
}variable-list;//定义的该结构体类型的结构体变量
描述一个人:
struct Person
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
double hight;//身高
};
结构体初始化:
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
};
int main()
{
//按照结构体成员的顺序初始化
struct Stu s = { "张三", 20, "男", "20230818001" };
printf("name: %s\n", s.name);
printf("age : %d\n", s.age);
printf("sex : %s\n", s.sex);
printf("id : %s\n", s.id);
//乱序初始化
struct Stu s2 = { .age = 18, .name = "lisi", .id = "20230818002", .sex = "⼥" };
printf("name: %s\n", s2.name);
printf("age : %d\n", s2.age);
printf("sex : %s\n", s2.sex);
printf("id : %s\n", s2.id);
return 0;
}
特殊结构体(匿名结构体类型)
这类结构体在声明时省略了标签名(tag),为匿名结构体类型。
struct//省略了标签名,不完全声明
{
int a;
char b;
float c;
}s1;
int main()
{
struct s2 = { 1,"1",3.14 };
return 0;
}
匿名结构体只能够使用一次,像上述代码中,s1可以正常创建,由于匿名结构体类型名是匿名的,不知道是什么类型名,所以 struct 并不是 s2 的结构体类型名,所以 s2 的创建并不合理。
又因为匿名结构体类型只能使用一次,所以匿名结构体类型创建出来的变量都是全局变量。
若想让 s2 合理或者想让匿名结构体能够多次使用,则需用 typedef 将匿名结构体重命名,如下:
typedef struct
{
int a;
char b;
float c;
}S;//S是匿名结构体重命名后的结构体类型名
int main()
{
S s2 = { 1,"1",3.14 };//S为类型名,s2为变量
return 0;
}
也正是因为匿名结构体没有结构体类型名,所以在结构体初始化时不能像正常结构体一样能够对结构体成员一次性进行初始化,需要通过结构体成员访问操作符(.或->)来进行初始化:
struct S
{
char name[20];
int num;
};
int main()
{
struct S s1 = { "m",2 };
}
struct
{
char name[20];
int num;
}s2;
int main()
{
struct s2 = { "m",2 };//报错
}
上述代码中,s1可以正常初始化,而s2却不行(编译器报错)。因为s2没有具体的结构体类型名(struct 不是变量s2的类型名),想初始化匿名结构体则需要使用结构体成员访问操作符(字符串除外)。
以下是字符串错误初始化/赋值方法
struct
{
char name[20];
int num;
double i;
}s;
int main()
{
s.num = 2;
s.name = "zhangsan";//字符串错误赋值
return 0;
}
注意:其中" " 引起来的字符串是常量字符串,不能直接赋值给字符数组,要把它的内容拷贝给字符数组(用strcpy)
所以正确字符串初始化方法:
strcpy(s.name,"zhangsan");
struct
{
int a;
char b;
float c;
}x;
struct
{
int a;
char b;
float c;
}a[20], *p;
int main()
{
p = &x;
}
主函数中代码合法吗?
答案是不合法。
匿名结构体没有确定的类型名所以编译器会将正常结构体和匿名结构体当做两个不同的类型。