C基础-11(结构体)

(内容为学习笔记,如有错误,还望指正,如有遗漏,还望补充) 

1.结构体 

1)结构体定义

        开发过程中,又是一个变量已经不满足我们对某一事物(对象)的表述了,这时候就需要使用多个变量来描述同一个事物,例如游戏中游戏角色有攻击力、防御力、生命值、法力值等,我们需要一种语法,能够将所有的属性封装成一个类型,即结构体。

Role            //结构体名
 { 
   int act;     //结构体变量 攻击力
   int def;     //结构体变量 防御力
   float HP;    //生命值
   float MP;    //法力值
 };

        结构体的本质是类型,是自定义的用来封装属性的类型。

2)定义结构体变量

/* 
定义结构体类型的关键字  struct 
student 是我们定义的结构体类型的名字 
{ 
    结构体的属性 
};//注意,这有分号。 
结构体的{}不表示作用域 
所以在{}内的代码,不是定义变量语句。 
{}内的代码,只是说明结构体类型中包含的属性有哪些。 
*/ 
struct student //这是结构体类型,在定义出结构体变量之前,不分配任何内存。 
{    
    char name[20]; 
    char number[20]; 
    int grade;       
    float score;     
}; 
 
int main() 
{ 
    /* 
    定义结构体变量  struct 结构体名 变量名; 
    注意:定义结构体变量时,struct不能省。 
    定义结构体变量之后,结构体变量中的成员才会被定义出来。 
    此时,变量a中包含了两个数组,两个变量。 
    此时a中的所有成员都没有有效值。 
    没有声明struct student a 就不给分配内存! 
    */ 
    struct student a; 
    printf("%d\n", sizeof(a));//48 
    return 0; 
}

3)访问结构体成员变量

        成员运算符

. //p.name 表示机构体变量p中的成员变量name

        二元运算,左值结构体变量,右值成员名称,运算得到结构体的成员对象本身,成员运算符的运算结果不是数值。

//a.name 运算得到变量a中的name成员本身,由于name是数组,所以a.name得到的是数组名 
strcpy(a.name, "Alice"); 
//a.number 运算得到变量a中的number成员本身,由于number是数组,所以a.number得到的是数组名 
strcpy(a.number,"17001001001"); 
//a.grade运算得到a中的grade成员本身,是一个int类型的变量 
a.grade = 90; 
//a.score运算得到a中的score成员本身,是一个float类型的变量 
a.score = 6000.00;

4)输出结构体成员变量

        不能直接把结构体变量格式化,只能一个一个属性单独进行格式化。

printf("name:%s,number:%s,grade:%d,score:%f\n", a.name, a.number, a.grade, a.score);

5)结构体指针

        结构体指针,就是普通的指针变量,和我们会之前学习的语法都是一样的。

成员运算符

->

成员运算符

.

        两个成员运算符的算法是相同,但是两者的左值类型不同, .的左值是结构体变量->的左值是结构体指针

6)结构体数组

初始化:

//完全初始化:
struct Student students[2] = {
        {"xiaoming", 18, 10010, "huaqing"},
        {"xiaoqiang", 19, 10011, "huaqing"}
    };
​
//部分初始化:
struct Student students[3] = {
        {"xiaoming", 18, 10010, "huaqing"},
        {"xiaoqiang", 19, 10011, "huaqing"}
    };
//部分初始化,没有值的元素,所有属性默认都是0
​
//默认初始化:
struct Student students[] = {
        {"xiaoming", 18, 10010, "huaqing"},
        {"xiaoqiang", 19, 10011, "huaqing"}
    };

7)结构体嵌套

struct date 
{
    int year;
    int month;
    int day;
};
​
struct id_card 
{
    char name[20];
    struct date birthday;
};

8)结构体大小计算

        结构体的大小计算中,我们应该先了解一个“行”的概念,结构体的大小一定是一“行”大小的整数倍,“行”的大小由结构体中占内存最大的成员决定

        例如下面的例子中,c是结构体student类型中最大的成员变量,则这个结构体变量的大小就是short的整数倍。

#include <stdio.h> 

struct student 
{
	char a;
	char b;
	short c;
};

int main()
{
    struct student s;
	printf("%p %p %p %p\n",&s, &s.a, &s.b, &s.c);
    /*
    打印会发现,&s和&s.a的值相同,但是两个地址的类型是不同的!可以+1验证
    &s.b是&s.a的值+1
    &s.c是&s.b的值+1
    */
	printf("%d\n", sizeof( struct student) );//4
}
char achar b
short cshort c

         再如下,结构体的成员变量在存储时依次存储,存储不下时会另起一行,每行大小是最大成员变量占用内存大小,a之后存不下b,所以b另起一行存储,c同理,所以占用了6个字节。

#include <stdio.h> 

struct student 
{
	char a;
	short b; 
	char c;
};

int main()
{
    struct student s;
	printf("%p %p %p %p\n", &s, &s.a, &s.b, &s.c);
	printf("%d\n", sizeof( struct student) );    //6
}	
char a
short bshort b
char c

         又如下,系统在分配地址的时候,除了char类型,都习惯分配偶数地址

#include <stdio.h> 

struct student 
{
	int a;
	char b;
	short c;   
	char d;
};

int main()
{
    struct student s;
	printf("%p %p %p %p %p\n",&s, &s.a, &s.b, &s.c, &s.d);
	printf("%d\n", sizeof( struct student) );    //12
}	
int aint aint aint a
char bshort cshort c
char d

        最后,在没有特殊强调是64位系统时,都按照32位系统算。32位系统“行”最多4字节。64位系统“行”最多8字节

        在32位系统中,int一定是独占一“行”,double一定是独占二“行”。

struct Node
{
	char c;
	double d;
};

int main()
{
	printf("%d\n", sizeof(struct Node));
	return 0;
}
char c
double ddouble ddouble ddouble d
double ddouble ddouble ddouble d
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值