目录
结构体使用注意:
1.给结构体中字符串赋值的写法
struct student test1;
test1.name = "小明" //c++和Java中可以,C语言不行,必须通过strcpy赋值
strcpy(test.name,"小明");
2. 野指针和空间问题
struct datas
{
char *p;
}
struct test
{
char p[128];
}
int main()
{
struct datas d;
strcpy(d.p,"哈哈哈");
printf("%s\n",d.p);
}
// 编译程序会崩溃,但是把main函数中的datas换成test就可以成功编译
原因是:test中定义的是数组,数组一旦被定义就自动生成空间,而datas中定义的是野指针,野指针必须要malloc。d.p=(char *)malloc(128),即使不初始化它,但至少它有空间了
结构体数组应用之学生成绩最高分最低分
#include <stdio.h>
#include <stdlib.h>
struct student{
int score;
char *name;
};
int main()
{
int i;
struct student stus[3];
struct student max;
struct student min;
max = min = stus[i];
for(i=0;i<sizeof(stus)/sizeof(stus[0]);i++)
{
printf("第%d个学生的名字:\n",i+1);
stus[i].name = (char *)malloc(128);
scanf("%s",stus[i].name); //因为name是指针(地址),就不用再取地址 &
printf("第%d个学生的分数:\n",i+1);
scanf("%d",&stus[i].score);
}
for(i=0;i<sizeof(stus)/sizeof(stus[0]);i++)
{
printf("第%d个学生的名字和分数是:\n",i+1);
printf("%s:%d\n",stus[i].name,stus[i].score);
}
printf("===========\n");
for(i=0;i<sizeof(stus)/sizeof(stus[0]);i++)
{
if(max.score<stus[i].score){
max = stus[i];
}
printf("最高分的人是:%s\n",max.name);
printf("最高分是:%d\n",max.score);
}
system("pause");
return 0;
}
注意:scanf不加&的情况:
接收的是一个地址的时候就不用&,例如stus[i].name那里。
结构体指针
1.如果用结构体指针,就不能用点运算符访问结构体中的变量,要用->
2.结构体指针的偏移问题:偏移整个结构体的大小
struct student
{
int score;
char name[128];
}
指针偏移一次,移动4+128=132个字节
结构体指针+函数实现学生成绩
#include <stdio.h>
#include <stdlib.h>
struct student
{
int score;
char *name;
};
struct student *init(int len)
{
int i;
struct student *p =(struct student *)malloc(len*sizeof(struct student));
//开辟len长度的空间来存放名字和分数
for(i=0;i<len;i++){
printf("输入第%d个学生的名字:\n",i+1);
p->name = (char *)malloc(128);
//指针所指向的地址需要存放数据的时候需要申请空间。
scanf("%s",p->name);
printf("请输入第%d个学生的分数:\n",i+1);
scanf("%d",&(p->score));
p++;
}
return p-len;
//容易落下,不返回或只返回p都影响下一个函数的执行,
//因为在该函数执行完后,指针已到了末尾,需要调回数组头的位置
}
void print(struct student *p,int len)
{
int i;
for(i=0;i<len;i++){
printf("第%d个学生的名字和分数是:%s:%d\n",i+1,p->name,p->score);
p++;
}
}
struct student *max(struct student *p,int len)
{ //先遍历
struct student *max = p;
int i;
for(i=0;i<len;i++){
if(max->score < p->score){
max = p;
}
p++;
}
printf("max %s:%d\n",max->name,max->score);
return max;
}
struct student *min(struct student *p,int len)
{
struct student *min = p;
int i;
for(i=0;i<len;i++){
if(min->score > p->score){
min = p;
}
p++;
}
printf("min %s:%d\n",min->name,min->score);
return min;
}
float average(struct student *p,int len)
{
int i;
int total = 0;
for(i=0;i<len;i++){
total += p->score;
p++;
}
printf("average:%f\n",(float)total/len);
return (float)total/len;
}
int main()
{
int len=0;
int i;
printf("人数:\n");
scanf("%d",&len);
struct student *ps = init(len); //定义个指针指向初始化函数,获取数组,len决定数组长度
print(ps,len);
max(ps,len);
min(ps,len);
average(ps,len);
system("pause");
return 0;
}
计算结构体的大小(面试)
结构体对其计算方式
两条原则:
1.结构体成员的偏移量必须是成员大小的整数倍
2.结构体大小必须是所有成员大小的整数倍(数组和结构体除外)
这种对齐方式很浪费空间,但是提高了计算机的访问效率
struct s1
{
char b; //1 {}
int c; //4 {} {}{}{} {}{}{}{}
char a; //1 {} {}{}{} {}{}{}{} {}
int d; //4 {} {}{}{} {}{}{}{} {} {}{}{} {}{}{}{}
char k; //1 {} {}{}{} {}{}{}{} {} {}{}{} {}{}{}{} {}
}
实际的大小是20
b大小是1,不偏移,没有偏移值(因为他是头),此时字节数是1。
c大小是4,偏移值(原则1)为1+3=4(+3是对齐用的),加上它的大小4,此时字节数为1+3+4=8
a大小是1,大小是1,不需要对其,直接加,此时字节数为1+3+4+1 = 9
d大小是4,偏移值为1+3=4(+3是对齐用的),加上它的大小4,此时字节数为1+3+4+1 +3 +4 = 16
k大小是1,不需要对其,直接加,此时字节数为1+3+4+1 +3 +4 +1= 17
但是根据原则2,还需要补齐到20(int和char的整数倍)
计算结构体中套结构体的大小:
struct test
{
char a;
int b;
struct test1
{
char aa;
int bb;
}
float c;
}
这种情况,计算test结构体的大小=1+3+4+4=12,不计算test1的大小,因为test1只是一个声明,不占空间,但如果test1是下面这种情况,就计算它的大小:
struct test1
{
char aa;
int bb;
}stu; (除了声明test1结构体还声明了stu这个变量)
#pragma pack()
对结构体对齐的方式进行限制
#pragma pack(4):限制跟4个字节对齐,如果结构体中最大的成员有超过4个字节的,就按4个字节对其;如果没超过,就按最大的成员大小算