自定义类型:结构体、枚举、联合

一、结构体:一些不同类型的值的集合,这些值称为结构体的成员变量。


1、结构体的创建

//创建一个简单的结构体:

struct stu{               //类型声明,结构体的标签
       char name[20];     //成员1,姓名
       int age;           //成员2,年龄
       char sex[3];       //成员3,性别
       char id[20];       //成员4,学号
};                        //末尾的分号不可以丢掉

2.结构体初始化

struct stu1{
      char name[20];
      int age;
};
struct stu1={"Walter",22};  //对stu1的变量同时赋初值(初始化)

3.结构体内存对齐(熟记四条规则)

  • 1.第一个成员在与结构体变量偏移量为0的地址处;
  • 2.其他成员变量要对齐到(对齐数)的整数倍地址处;

  • 3.结构体的总大小为成员里最大对齐数的整数倍;

  • 4.如果有结构体的自引用情况,还是对齐到最大对齐数的整数倍,结构体大小就是所有最大对齐数的整数倍。

画个图解释一下:

自定义类型:结构体、枚举、联合_第1张图片

同样我们可以用一个预处理指令来修改默认对齐数,如下:

#pragma pack(8)    //设置默认对齐数为8;
#pragma pack()     //设置对齐数还原为默认;

4.结构体传参

struct s1{
    int data[1000];
    int num;
};

struct s1  s={{1,2,3,4},50};

//结构体传参数

void printf1(struct s1 s){
     printf("%d\n",s.num);
}

//结构体地址传参数

void printf2(struct s1* ps){
      printf("%d\n",ps->num);
}

int main(){
     printf1(s);
     printf2(&s);
return 0;
}

首选printf2函数,因为函数传参的时候,参数是需要压栈的,如果直接传结构体会导致系统开销较大,因此效率和性能大大降低。

结构体传参的时候,要传结构体的地址!

4.位段

1)位段的成员必须是int、unsigned int、signed int。

2)位段的成员名后面有一个冒号和一个数字。

struct A{
    int _a:2;
    int _b:4;
};

位段的大小在不同的编译器里是不一样的,所以研究位段的内存布局没有意义!


二、枚举:把所有可能的数值一一列举,在C中与int有着等价效果。


enum sex{            //enum sex 是枚举类型
     Male;           //枚举常量,默认初始值为0
     Female;         //枚举常量,默认初始值为1
     Unkonw;         //枚举常量,默认初始值为2
};

三、联合(共用体):一系列成员共用同一块空间的集合体


由于联合中各成员共用同一段空间,所以联合长度至少可以容纳最大的成员。

但是当最大成员大小不是 最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍。

干货,一道笔试题:利用union编写程序判断CPU是big-endian还是litter-endian


#include
 
int main()
{
    union Test
    {
        unsigned int a;
        unsigned char b;
    }tmp={0x12345678};

    //如果打印出的是0x78,表明是litter-endian
    //如果打印出的是0x12,表明是big-endian
 
    if(tmp.b==0x78)
        printf("The endian of cpu is litter-endian.\n");
    else
        printf("The endian of cpu is big-endian.\n");
 
    return 0;
}

 

你可能感兴趣的:(记录,结构体,自定义类型,大小端)