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

结构体


结构体的声明

基础知识

结构是一些值的集合, 这些值成为成员变量。结构得每个成员可以是不同类型的变量。

结构的声明

struct tag//结构体标签
{   
     member-list; //成员列表
}variable-list;//变量

例如描述一个学生:

struct Stu 
{
     char name[20];//名字
     int age;//年龄
     char sex[5];// 性别  
     char id[20];// 学号
};//分号不能丢

特殊的声明:

在声明结构体的时候,可以不完全的声明。
比如:

// 匿名结构体类型
struct 
{   
    int a;    
    char b;    
    float c; 
}x; 
struct 
{   
    int a; 
    char b;   
    float c; 
}a[20], *p;

上面的两个结构在声明的时候省略掉了结构体标签。

那么

//在上面代码的基础上,下面的代码合法吗?
p = &x; 

警告
编译器会把上面的两个声明当成完全不同的类型。所以是非法的。

结构的成员

结构体成员的访问

  • 结构体变量访问成员是通过点操作符(.)访问的
    例如:
    这里写图片描述
    如何访问s的成员?
struct S s;
strcpy(s.name, "zhangsan");//使用.访问name成员
s.age = 20;//
  • 结构体访问指向变量的成员 有时候我们得到的不是一个结构体变量,而是一个指向结构体的指针。那么该如何访问成员,如下:
struct S
{
    char name[20];
    int age;
}s;

void print(struct S* ps)
{
    printf("name = %s   age = %d\n", (*ps).name, (*ps).age);
    printf("name = %s   age = %d\n", ps->name, ps->age);
}

结构体变量的定义和初始化

如何定义变量?

struct Point
{
    int x;
    int y;
}p1;            //声明类型的同时定义变量p1;
struct Point p2;//先声明结构体类型,再定义结构体变量p2;

//初始化:定义变量同时赋初值。
struct Point p3 = {x, y};
struct Stu
{
    char name[15];
    int age;    
};
struct Stu s = {"zhangsan", 20};//初始化

struct Node 
{    
    int data;   
    struct Point p;    
}n1 = {10, {4,5}, NULL};            //结构体嵌套初始化

struct Node n2 = {20, {5, 6}, NULL};// 嵌套初始化

结构体内存对齐

这里写图片描述

结构体传参

struct S 
{  
    int data[1000];    
    int num;  
};
struct S s = {{1,2,3,4}, 1000}; 
//结构体传参
void print1(struct S s) 
{    
    printf("%d\n", s.num); 
}  
//结构体地址传参 
void print2(struct S* ps) 
{    
    printf("%d\n", ps->num);
}
int main() 
{    
    print1(s);  // 传结构体   
    print2(&s); // 传地址   
    return 0; 
}

首选print2函数
原因:
函数传参的时候,参数是需要压栈的。
如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。
结论
结构体传参的时候要传结构体地址。

位段

位段的声明和结构体是类似的,有两个不同:

1.位段的成员必须是 int 、unsigned int 或 signed int
2.位段的成员名后面有一个冒号和数字:

例如:

struct A
{    
    int _a:2;    
    int _b:5;    
    int _c:10;    
    int _d:30; 
};//A就是一个位段类型

位段的内存分配

  1. 位段的成员可以是 int unsigned int signed int 或者是 char类型。
  2. 位段的空间上是按照需要以四个字节(int)或一个字节(char)的方式来开辟的。
  3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

位段的跨平台问题

这里写图片描述

枚举

枚举类型的定义

enum Day// 星期 
{    
    Mon,    
    Tues,
    Wed,    
    Thur,    
    Fri,    
    Sat,    
    Sun
}; 
enum Sex//性别
{    
    MALE,    
    FEMALE,    
    SECRET 
};
enum Color//颜色
{    
    RED,    
    GREEN,    
    BLUE 
};

以上都是枚举类型
{}中的内容是枚举类型的可能取值,也叫枚举常量。这些常量都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。
例如:

enum Color 
{    
    RED=1,    
    GREEN=2,    
    BLUE=4 
};

枚举的优点

  1. 增加代码的可读性和可维护性。
  2. 和#define定义的标识符相比枚举有类型检查,更加严谨。
  3. 防止了命名污染。
  4. 便于调试。
  5. 使用方便,一次可以定义多个常量。

联合

定义:
这种类型定义的变量也包含一系列成员,特征是这些成员共用同一块空间。
比如:

//联合类型的声明
union Un 
{    
    char c;    
    int i; 
};
//联合变量的定义
union Un un;

联合大小的计算

  • 联合的大小至少是最大成员的大小。
  • 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍处。

猜你喜欢

转载自blog.csdn.net/lzhcr123/article/details/80782819