结构体的定义
结构体是一种构造数据类型,他将不同类型的数据组合成一个有机的整体以便于引用。
结构体的定义方法
1.先定义结构体类型,再去定义结构体变量
struct stu{
成员列表;
};
struct stu str;
2.在定义结构体类型时顺便定义结构体变量,之后还可以再定义。
struct stu{
成员列表;
}A,B;
3.给结构体类型取别名,用别名去定义结构体变量
typedef struct stu{
成员列表;
}STU;
STU A;
结构体变量的使用
一般形式为:结构体变量名.成员名,结合下面代码理解吧
#include <stdio.h>
#include <string.h>
//结构体类型的声明
struct stu{
char name[20];
int score;
int id;
float h;
char sex;
};
int main(int argc, char *argv[])
{
//定义结构体变量并初始化
struct stu ms={"john",0,160,178,'y'};
strcpy(ms.name,"jack");
ms.score=120;
ms.id=123;
ms.h=180;
printf("name=%s\nscore=%d\nid=%d\nheight=%.2f\nsex=%c\n",ms.name,ms.score,ms.id,ms.h,ms.sex);
return 0;
}
注意:
1.在使用结构体变量时,不能将结构体类型变量作为一个整体加以引用,而只能对结构体类型变量中的各个成员分别引用
2.只能对最低级的成员进行赋值或存取以及运算。
3.对成员变量可以向普通变量一样进行运算。
4.同一结构体类型的结构体变量可以相互赋值
结构体变量初始化
一般形式:
struct 结构体名 变量名={数据};
结构体数组
1.定义:由若干个相同类型的结构体构成的集合,称他们为结构体数组
2.定义方法:
struct stu{
int num;
char name[20];
char sex;
};
struct stu edu[3];
结构体元素的引用:数组名【下标】例:edu[0];
数组内元素的使用:例:
注意:1.可以将一个结构体数组元素赋给同一结构类型的数组中的另一个元素,或赋值给同一类型变量。
2.不能把结构体数组元素作为一个整体直接进行输入输出
struct stu{
int num;
char name[20];
char sex;
};
struct stu edu[3];
edu[0].num=101;
strcpy(edu[1].name,"lucy");
结构体指针
可以设定一个指针变量来指向一个结构体变量,此时指针变量的值是结构体变量的起始地址,该指针为结构体指针。
定义方法:
struct 结构体名 *结构体指针名
结构体指针的应用场景
1.保存结构体变量的地址
#include <stdio.h>
#include <string.h>
//结构体类型的声明
struct stu{
char name[20];
int score;
int id;
float h;
char sex;
};
int main(int argc, char *argv[])
{
//定义结构体变量并初始化
struct stu ms={"john",0,160,178,'y'};
strcpy(ms.name,"jack");
ms.score=120;
ms.id=123;
ms.h=180;
printf("name=%s\nscore=%d\nid=%d\nheight=%.2f\nsex=%c\n",ms.name,ms.score,ms.id,ms.h,ms.sex);
//结构体指针
struct stu *p=&ms;
// p->name 相当于 (*p).name
strcpy(p->name,"greec");
printf("name=%s\nscore=%d\nid=%d\nheight=%.2f\nsex=%c\n",p->name,p->score,p->id,p->h,p->sex);
return 0;
}
2.传结构体变量的地址
typedef struct stu{
int num;
char name[20];
float score;
}STU;
void fun(STU *p)
{
p->num=101;
(*p).score=87.6;
strcpy(p->name,"lucy");
}
int main()
{
STU girl;
fun(&girl);
printf("%d%s%f\n",girl.num,girl.name,girl.score);
return 0;
}
3.传结构体数组的地址
typedef struct stu{
int num;
char name[20];
float score;
}STU;
void fun(STU *p,int n)
{
int i;
for(i=0;i<n;i++)
printf("%d%s%f\n",p[i].num,p[i].name,p[i].score);
}
int main()
{
STU edu[3]={{},{},{}};
fun(edu,3);
}
注意点!!
结构体变量地址:
typedef struct stu{
int num;
char name[20];
float score;
}STU;
STU boy;
&boy;//类型是STU *
&(boy.num)//类型是int *
//虽然结果一样都是结构体的首地址,但是类型不同
结构体数组的地址就是结构体数组中第0个元素的地址
typedef struct stu{
int num;
char name[20];
float score;
}STU;
STU edu[3];
edu;//STU *
&edu[0];//STU *
&(edu[0].num);//int *
//都是结构体数组的地址,但是类型不同哦
结构体内存分配和字节对齐
结构体变量大小是其所有成员大小之和,但是在实际给结构体变量分配内存的时候,是有规则的。
1.以多少个字节为单位开辟内存,看哪个基本类型的成员占字节数多,就以它大小为单位开辟内存。
2.字节对齐原则:(为了提高访问效率)不理解的时候可以画图!!!
char | 1字节对齐 |
short | 2字节对齐 |
int | 4字节对齐 |
long int | 32位:4字节 64位:8字节 |
float | 4字节对齐 |
double | 8字节对齐 |
让我们看几个例子把:
//结构体的内存分配和字节对齐原则
#include <stdio.h>
struct A{
char a;
char b;
int c;
};
struct B{
char a;
int b;
char c;
};
struct C{
char a;
char b;
char c;
int d;
};
struct D{
char a;
short c;
char d;
int b;
double f;
};
int main(int argc, char *argv[])
{
struct A a;
printf("%ld\n",sizeof(a));
struct B b;
printf("%ld\n",sizeof(b));
struct C c;
printf("%ld\n",sizeof(c));
struct D d;
printf("%ld\n",sizeof(d));
return 0;
}
看看结果是否和你想得一样呢?
让我们画图分析一下D的结果你应该就理解了!!!
X86cpu能直接访问对齐的数据,当它试图访问一个未对齐的数据时,会在内部进行一系列调整,在访问内存时,如果以4字节对齐,访问效率会高很多,这种现象的原因在于访问内存的硬件电路,一般情况下,地址总线总是按照对齐后的地址来访问的。
在上述例子中,为了保证4字节对齐,有了图上的内存分配情况,在之后的练习中可以通过画图来解决此类问题,牢记对齐规则!!!