结构体类型的声明
结构体初始化
结构体成员访问
结构体传参
结构体的声明
1.1结构体基础知识
概念:结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
1.2结构的声明
struct tag { member-list; }variable-list;
例如:
struct book
{
int price;
char name[20];
};
这里的prince和name都是book的成员变量。
struct book
{
int price;
char name[20];
}b3,b4,b5;
int main()
{
struct book b1;
struct book b2;
return 0;
}
这里b3,b4,b5都是全局变量,而b1,b2是局部变量。如果定义时,写成typedef struct book,那么定义新变量可以用book当作结构体类型。
typedef struct book
{
int price;
char name[20];
}book;
int main()
{
struct book b1;
struct book b2;
book b3;
return 0;
}
1.3结构成员的类型
结构的成员可以是标量、数组、指针,甚至是其他结构体。
1.4结构体变量的定义和初始化
struct S
{
char c;
char arr[10];
int* p;
}s1, s2;//声明类型的同时定义变量s1,s2
struct S s3;//定义结构体变量p2
struct B
{
int a;
struct S s;
double d;
}sb1, sb2;//声明类型的同时定义变量s1,s2
struct B sb3;//定义结构体变量p2
int main()
{
int a = 10;
struct S s4 = {'c', "zhangsan", &a};
int b = 10;
struct B sb4 = { 100, {'q', "lisi", &b}, 3.14};//结构体嵌套初始化
return 0;
}
也可以这样定义和访问成员:
struct Book
{
char name[20];
int price;
};
void print(struct Book* p)
{
printf("%s %d\n", p->name, p->price);//#2 结构体指针->结构体成员
}
int main()
{
struct Book b1 = { "hehe", 66 };
struct Book b2 = { .price = 80, .name = "xixi" };//#1 结构体变量.结构体成员
printf("%s %d\n", b1.name, b1.price);
printf("%s %d\n", b2.name, b2.price);
print(&b1);//struct Book* p1 = &b1;//只给了地址,要访问成员
return 0;
}
2. 结构体成员的访问
结构体访问成员
结构体变量的成员是可以通过点操作符(.)访问。点操作符需要两个操作数。
例如:
struct stu
{
char name [20];
int age;
};
struct Stu S;
我们可以看到结构体S里面有成员name 和age.如果我们需要访问成员,那么需要结构体指针指向变量的成员。
struct Stu
{
char name[20];
int age;
};
void print(struct Stu* ps)
{
printf("name = %s age = %d\n", (*ps).name, (*ps).age);
//使用结构体指针访问指向对象的成员
printf("name = %s age = %d\n", ps->name, ps->age);
}
int main()
{
struct Stu s = { "zhangsan", 20 };
print(&s);//结构体地址传参
return 0;
}
3.结构体传参
例:
struct S
{
int data[100];
int num;
};
void print1(struct S ss)
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", ss.data[i]);
}
printf("%d \n", ss.num);
}
void print2(struct S* ps)
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", ps->data[i]);
}
printf("%d \n", ps->num);
}
int main()
{
struct S s = { {1,2,3,4,5},100 };
print1(s);
print2(&s);
return 0;
}
上面有两种传参print1(结构体传参)和print2(结构体地址传参)的方式。两种传参还是有区别的,如果对比上面的print1和print2哪个更好?应该是print2函数比较好。
是因为:
函数传参的时候,参数是需要压栈的。 如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的 下降。
因此:print2只需要一个指针4/8个字节大小,但是print1是有两个int整形数组和整形的大小,效率远不如print2.
结论:结构体传参的时候,要传结构体的地址。