结构体

结构体的声明

struct  tag   //tag为结构体标签
{
    member-list; //结构体成员变量
}variable-list; 

例如描述一个学生:

struct Stu
{
       char name[20]; //姓名
       int age;       //年龄
       char sex[5];   //性别
       char sno[20];  //学号
};  //分号不能丢

特殊的结构体声明
匿名结构体类型

struct
{
     int a;
     char b;
     float c;
 }x; 
struct
{
     int a;
     char b;
     float c;
 }a[20],*p;

  以上两个结构体在声明的时候省略掉了结构体标签tag;所以在结构体后如果不直接创建结构体变量x,a[20],*p以后将无法使用此结构体。
在上面代码的基础上,p=&x合法吗?
编译时会发现:
这里写图片描述
  由于是匿名结构体,编译器会将上面的两个结构体声明当成完全不同的类型 ,所以是非法的。
结构体的成员
结构体的成员可以是标量,数组,指针,甚至其他结构体。
结构体成员的访问
1-> 结构体变量访问成员。 结构体变量的成员是通过点操作符(.)访问的。

#include<stdio.h>
#include<stdlib.h>
struct Stu
{
    char name[20];
    int age;
};
int main()
{
    struct Stu s;
    strcpy(s.name, "zhangsan");  //使用.访问name成员
    s.age = 20;                  //使用.访问age成员
    system("pause");
    return 0;
}

2-> 结构体访问指针变量的成员。有时候我们得到的不是一个结构体,而是指向一个结构体的指针,通过(->)来访问。

#include<stdio.h>
#include<stdlib.h>
struct Stu
{
    char name[20];
    int age;
};
int main()
{
    struct Stu *s;
    strcpy(s->name, "zhangsan");  //使用->访问name成员
    s->age = 20;                  //使用->访问age成员
    system("pause");
    return 0;
}

结构的自引用
问题:在结构体中包含一个类型为该结构体本身的成员是否可以?
答:不可以

struct node
{
    int data;
    struct node next;
};

结构体还没有定义,成员就已经使用,而且它的成员结构体的大小无法计算,所以肯定是不可以的。
正确的自引用方式:

struct node
{
    int data;
    struct node *next;
};

结构体的定义和初始化
1. 定义

struct Point
{
    int x;
    int y;
}p1;  //声明类型的同时定义变量p1
struct Point p2;//定义结构体变量p2
  1. 初始化
struct Point
{
    int x;
    int y;
}p1 = { 3, 4 };  //声明类型的同时定义变量p1且赋初值
struct Point p2 = { 1,2 };//定义结构体变量p2的同时赋初值
struct s
{
    int data;
    struct Point p1;
    struct s*next;
}n1 = { 10, {5,6},NULL }; //结构体嵌套初始化

结构体内存对齐
结构体内存对齐的规则:
1. 第一个成员在结构体变量偏移量为0的地址处。
2. 其它成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数=编译器默认的一个对齐数与该成员大小的较小值
VS中默认值为8,Linux中默认值为4。
3. 结构体的总大小为最大对齐数的整数倍。
4. 如果嵌套了结构体,嵌套的结构体对其到自己的最大对齐数的整数倍;结构体的大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
练习1(不嵌套结构体)

#include<stdio.h>
#include<stdlib.h>
struct s1
{
    char c1;
    int i;
    char c2;
};
int main()
{
    printf("%d\n", sizeof(struct s1));
    system("pause");
    return 0;
}

分析:
这里写图片描述
运行:
这里写图片描述
练习2(嵌套结构体)

#include<stdio.h>
#include<stdlib.h>
struct s1
{
    char c1;
    int i;
    char c2;
};
struct s2
{
    char c;
    struct s1 p;
    double d;
};
int main()
{
    printf("%d\n", sizeof(struct s2));
    system("pause");
    return 0;
}

分析:
这里写图片描述
运行:
这里写图片描述
设置结构体如何节省空间?
让占用内存小的成员尽量集中在一起。

#include<stdio.h>
#include<stdlib.h>
struct s1
{
    char c1;
    int i;
    char c2;
};
struct s2
{
    char c1;
    char c2;
    int i;
};
int main()
{
    printf("%d\n", sizeof(struct s1));
    printf("%d\n", sizeof(struct s2));
    system("pause");
    return 0;
}

s1和s2的类型成员一模一样,但是:sizeof(struct s1)=12; sizeof(struct s2)=8;
结构体传参

#include<stdio.h>
#include<stdlib.h>
struct s1
{
    char c1;
    int i;
    char c2;
};
void print1(struct s1 s)
{
    printf("%c\n", s.c1);
}
void print2(struct s1 *s)
{
    printf("%c\n", s->c1);
}
int main()
{
    struct s1 s = { 'a', 4, 'b' };
    print1(s);
    print2(&s);
    system("pause");
    return 0;
}

哪一个更好??
首选print2。
原因:函数传参时,参数需要压栈,如果传递的是结构体,结构体过大,参数压栈的系统开销就比较大,会导致性能下降。
所以最好传地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值