C---结构体

结构体使用注意:

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个字节对其;如果没超过,就按最大的成员大小算

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值