首页 > 其他分享 >0809结构体与共用体

0809结构体与共用体

时间:2024-08-11 11:55:18浏览次数:13  
标签:struct int 成员 score 对齐 共用 字节 结构 0809

 

结构体


背景:

如果我们要描述一个学生的成绩,学号,体重还有名字等,就应该定义以下的数据类型等来储存数据。

float score[30];
int sno[30];
float height[30];
char name[30][30];

那为了方便引用和使用一些复杂数据,于是便定义了结构体类型。
结构体类型 ---- 用来描述复杂数据的一种数据类型
 

一般语法:


struct 结构体名
{
   成员列表;
} ;

解释:

        (1) struct 关键字 
            表示 是在构造一个结构体的类型 
        (2) 结构体名    
            用来 描述 结构体这个类型 一个名称 
        (3) 成员列表 
            表示 要描述的复杂数据 中用到的 具体的成员变量
            定义的方式,与定义变量的方式相同,以字母,下划线,数字组成。
            多个成员变量之间,用分号隔开。
        (4) 最后 有一个 分号 表示 结束 

结构体类型的定义形式:


//形式1 先定义类型,然后定义变量 
struct demo
{}; 
struct demo d;

//形式2 定义类型的同时,定义变量 
struct demo
{
}d; //

//形式3 定义类型的同时,定义变量,可以省略 结构体名  
struct 
{
}d; //如果,结构体类型只用一次 

    

eg:
struct student 
{
    char name[30]; // 
    int sno;
    float score;
    char sex;  
}; //表示 定义出 一个 数据类型 


注意:
  1.结构体类型的使用的过程 
    a.先定义出类型
    b.定义变量
     struct 结构体名  变量名;
   


结构体初始化:


struct student s = {};

初始化
  看每个成员变量,具体是什么数据类型。
  根据 各个成员变量 自身的数据类型,进行初始化。
  初始化的顺序,按照定义的顺序,依次初始化

结构体变量的引用:
  //结构体数据 引用时,一般是引用到具体的成员数据 
  引用到成员 
  运算符 
     .   //结构体成员运算符 
     
使用:
   结构体变量名.成员名    //表示 访问 某个结构体 的成员 
练习:
   描述一个学生类型 

#include <stdio.h>

// 定义学生信息的结构体
typedef struct {
    char name[50];  // 学生姓名,假设最大长度为50个字符
    float weight;   // 学生体重,使用浮点数表示
    float score;    // 学生分数,使用浮点数表示
    int studentID;  // 学生学号,使用整数表示
} Student;

int main() {
    // 创建一个学生信息的实例
    Student stu = {
        .name = "张三",
        .weight = 60.5,  // 单位:千克
        .score = 89.5,   // 假设分数范围是0到100
        .studentID = 202401
    };

    // 打印学生信息
    printf("学生姓名: %s\n", stu.name);
    printf("学生体重: %.2f kg\n", stu.weight);
    printf("学生分数: %.2f\n", stu.score);
    printf("学生学号: %d\n", stu.studentID);

    return 0;
}

   
练习:


    准备3个学生的信息,
    求他们平均分 
 
   提示:

用 struct student s[3]; //结构体类型的数组 

           ->  指向结构体成员 运算符 
   
           结构体指针->成员名   
   
           结构体变量名.成员名   

 

#include <stdio.h>

// 定义学生信息的结构体
typedef struct {
    char name[50];
    float weight;
    float score;
    int studentID;
} Student;

int main() {
    // 创建三个学生信息的数组
    Student students[3] = {
        {"张三", 60.5, 89.5, 202401},
        {"李四", 55.0, 92.0, 202402},
        {"王五", 65.0, 88.0, 202403}
    };

    // 计算平均分
    float totalScore = 0.0;
    for (int i = 0; i < 3; i++) {
        totalScore += students[i].score;
    }
    float averageScore = totalScore / 3;

    // 打印平均分
    printf("三个学生的平均分是: %.2f\n", averageScore);

    return 0;
}


练习:
     打印出 成绩最高的学生的信息 
     

void IpStu(struct student *s[],int len)
{
    int i=0;
    
    for(i=0;i<len;i++)
    {
    printf("Input a Sno : ");
    scanf("%d",&s[i]->sno);
    printf("Input a sname: ");
    scanf("%s",s[i]->name);
    printf("Input a sex: ");
    scanf("%d",&s[i]->sex);
    printf("Input a score: ");
    scanf("%d",&s[i]->score);
    }

}
void printfTopOne(struct student *s,int len)
{
    int i;
    float temp=s->score;
    for(int j=1;j<len;j++)
    {
        if((s[j]->score) >temp)
        {
            i=j;
            temp=(s+j)->score;
        }
    }
    printf("sno= %d\n",s[i].sno);
    printf("sname= %s\n",s[i].name);
    printf("sex= %d\n",s[i].sex);
    printf("score= %d\n",s[i].score);
}
                                            
 int main()
 {
     int x;
 
     struct student s[3];
     IpStu(s,3);
     printfTopOne(s,3);          
     return 0;
 }
 #endif

怎么算结构体类型的大小

        成员大小:结构体的总大小是其所有成员大小的总和。

        内存对齐:编译器可能会在结构体的成员之间插入填充字节(padding),以确保每个成员都位于特定的内存地址边界上。这称为内存对齐,它通常取决于平台和编译器的设置。例如,如果一个成员需要4字节对齐,那么在它之前可能会插入1到3个字节的填充,以确保它的地址是4的倍数。

        结构体的对齐:结构体的总大小也受最大成员对齐要求的影响。编译器会选择结构体中最大成员的对齐要求作为整个结构体的对齐要求,并可能在最后一个成员之后插入填充,以确保结构体的总大小是该对齐要求的倍数。


        1.在32位的平台上,默认都是按4字节对齐的。 
        2.对于成员变量,
           各自在自己的自然边界上对齐。
           char  -- 1字节 
           short -- 2字节 
           int   -- 4字节 
        3.如果 成员变量中有比4字节大。      
          此时 整个结构体 按照4字节对齐。 //32位的平台 
        4.如果 成员变量中没有有比4字节大。  
          此时 整个结构体 按照最大的那个成员对齐。   
          //32位的平台   
          //如果有超过4字节 ,按照4字节对齐
          //如果没有超过4字节的,则按成员变量中最大对齐 
         ----------------------------------------------
          //64位的平台
          //如果超过4字节的,按超过的最大的成员变量对齐 
          //如果没有超过4字节的,则按成员变量中最大对齐

举例:

struct student
{
    int a;
    char s;
    short b;
};

//a占四个字节,char s 占一个,short占两个;但是最后的内存大小要是4的倍数(在32位下),所以是8个字节;

eg:
struct student
{
    int a;//4个
    char s;//1个
    long long b;//16
};
 //32位的平台 ,如果有超过4字节 ,按照4字节对齐。所以结果为24
 //64位的平台,如果超过4字节的,按超过的最大的成员变量对齐 ,所以结果为32;
       

注意:同类型的结构体变量之间 ,可以相互赋值 
struct student s1;
struct student s2;
s2 = s1; 


qsort()  

void qsort(
           void *base,    //要排序的数组的首地址 
           size_t nmemb,  //数组元素的个数 
           size_t size,   //单个元素的大小 
           int (*compar)(const void *, const void *) //比较函数 --- 提供比较依据
           );
功能:
    排序数组

 
    举例:对三个学生的分数进行排序;

struct student
 {
     int sno;
     char name[20];
     int sex;
     int score;

 };

int compar(const void *a,const void *b)
{
      const struct student *p=a;
      const struct student *q=b;
      return p->score*100 - q->score*100;
}

int main()
{

    struct student s[3]={{110,"li",1,87},{111,"hua",1,59},{112,"k",1,99}};
    qsort(s,3,sizeof(s[0]),compar);

    for (int i = 0; i < 3; i++)                                                                              
    {
          printf("sno: %d, name: %s, sex: %d, score: %d\n", s[i].sno, s[i].name, s[i].sex, s[i].score);
    }
    puts("\n");
    return 0;
}


    
  
        
 
共用体

共用体(Union)是一种特殊的数据类型
它允许在同一个内存位置存储不同的数据类型。
共用体的所有成员共享同一块内存空间,
因此同一时间只能存储其中一个成员的值。

共用体的定义和结构体类似,使用关键字union,后面跟着成员列表。
每个成员可以是不同的数据类型,

但共用体的所有成员都共享同一块内存空间,大小取决于最大的成员


   
语法:


  union 共用体名
  {
     成员变量;
  };
   
   

eg:
  union demo
  {
     char a;
     short b;
     int c;
  };


  
  共用体:
       共用了一块内存空间 
       公用了最大成员的空间 
       
  注意:
  1.共用体初始化时,只能给一个值,默认时给到第一个成员的。
  2.共用体变量中的值,取决与最后一次给到的值,还要看能影响几个字节。
  
  对比 结构体
  1.结构体中各个成员 拥有自己独立空间
  2.共用体中,成员共用一块空间
  

 
  
考点:
   用共用体 判断大小端
  
#include <stdio.h>


// 定义一个共用体,
typedef union {
    int i;
    char c;  
} EndianUnion;

// 函数用于判断大小端
int is_big_endian() {
    EndianUnion u;
    u.i = 1; // 将共用体的i成员设置为1
    return u.c == 1; // 如果c的值是1,则是大端
}

int main() {
    if (is_big_endian()) {
        printf("大端字节序 (Big-endian)\n");
    } else {
        printf("小端字节序 (Little-endian)\n");
    }
    return 0;
}

标签:struct,int,成员,score,对齐,共用,字节,结构,0809
From: https://blog.csdn.net/qq_63145217/article/details/141068929

相关文章

  • 取药机器人的机械结构设计(开题报告)
    开题报告题目:取药机器人的机械结构设计一、选题背景与意义随着中国社会老龄化趋势的加剧,医疗需求特别是慢性病管理需求显著增加,医院药房面临巨大的工作压力。传统的人工取药方式不仅效率低下,还易因疲劳导致错误,影响患者用药安全。因此,开发自动化取药机器人成为提升医疗服......
  • 【数据结构】—— 内部排序算法详解
    1、前言2、常见排序算法3、排序算法实现3.1直接插入排序3.2希尔排序3.3选择排序3.4堆排序3.5冒泡排序3.6快速排序3.6.1单趟排序hoare法挖坑法双指针法3.6.2非递归实现3.6.3常见问题基准值的选取小区间优化3.7归并排序3.7.1递归实现3.7.2非递归实现3.8......
  • Python数据结构:列表详解(创建、访问、修改、列表方法)①
    @[toc]Python中的列表是一个非常强大的数据结构,它允许我们存储、访问和操作一系列的数据。列表可以包含任何类型的对象,包括数字、字符串、甚至其他列表。本文将详细介绍Python列表的创建、访问、修改以及列表方法,并附上一个综合的例子,全面展示列表在实际编程中的应用。一......
  • 25版王道数据结构课后习题详细分析 第三章栈、队列和数组 3.2 队列 选择题部分
    一、单项选择题————————————————————————————————————————解析:栈和队列的逻辑结构都是线性结构,都可以采用顺序存储或链式存储,C显然也错误。只有D才是栈和队列的本质区别,限定表中插入和删除操作位置的不同。正确答案:D—————......
  • 线性结构查找(顺序、折半、分块)
    对于线性结构的查找,应掌握其查找的过程、构造判定树、分析平均查找长度等。一、顺序查找顺序查找又称线性查找,它对顺序表和链表都是适用的。对于顺序表,可通过数组下标递增来顺序扫描每个元素;对于链表,可通过指针next来依次扫描每个元素。顺序查找通常分为对一般的无......
  • 树形结构查找(B树、B+树)
    平衡树结构的树高为O(logn),平衡树结构包括两种平衡二叉树结构(分别为AVL树和RBT)以及一种树结构(B-Tree,又称B树,它的度大于2)。AVL树和RBT适合内部存储的应用,而B树适合外部存储的应用。对于B树,应掌握其查找、插入以及删除的操作过程,对于B+树(一种B树的变形树......
  • UOJ #712. 【北大集训2021】简单数据结构
    Description你有一个长度为\(n\)的序列\(a\),下面你要进行\(q\)次修改或询问。给定\(v\),将所有\(a_i\)变为\(\min(a_i,v)\)。将所有\(a_i\)变为\(a_i+i\)。给定\(l,r\),询问\(\sum_{i=l}^ra_i\)。\(1\leqn,q\leq2\times10^5,0\leqa_i,v_i\leq10^{12}......
  • 【JVM】Java跨平台性质及Java虚拟机内存结构
    目录Java为什么可以跨平台Java虚拟机的内存结构简单聊聊~Java为什么可以跨平台Java编写的代码可以做到一次编译,多平台运行。这是为什么呢?我们在使用Java之前先要去按照对应操作系统版本的JDK,JDK中包含了Java编译器,Java虚拟机,一些类库等。在编写完代码之后,代码通过编译......
  • 数据结构之线性表(单链表的实现)
    目录一、单链表的原理二、单链表的实现1.单链表的定义2.单链表的初始化3.清空单链表4.单链表是否为空5.单链表的长度6.获取指定位置i的元素7.获取指定元素e的位置  8.向链表中插入指定位置的元素9.向链表中删除指定位置的元素10.遍历链表中的元素三、打印测......
  • 数据结构:顺序二叉树(堆)
    目录前言一、堆的实现 1.1头文件1.2堆的初始化及销毁1.3 堆的插入1.4堆的删除1.5取堆顶数据和判空前言   前面我们讲了二叉树有顺序结构和链式结构,今天就来讲一下顺序结构  普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而......