C语言结构体和枚举类型

一:1>结构体的概念:

  构造类型是一组功能相同的,若干个“成员”或者“元素”组成的集合。

  数组也是构造类型,指一组有相同数据类型的元素组成的集合

  2>结构体的定义:

  格式:struct 结构体名称{

        成员属性

}

  注意:结构体定义完成以后,并不会分配存储空间

   1)定义结构体变量的几种方法

结构体变量:结构体是一个类型,用结构体定义的变量就是结构体体变量

特点:包含了一系列的成员(复合的数据类型)

    

  (1)定义结构体的同时,定义结构体变量

struct Student{

char *name;

int score;

}stu1,stu2; //定义了两个结构体变量

(2)先定义结构体,在定义结构体变量

struct iPhone{

int model;

char cpu[5];

int memory;

int screen_size;

};

格式:

struct 结构体名 结构体变量名;

struct iPhone iphone6; struct iPhone iphone6plus,ip6; //两个结构体变量

(3)使用匿名结构体定义结构体变量

struct{ //匿名的结构体

char *model;

int pmcc;

}dell,lenovo; //定义了两个结构体变量

  2)..结构体成员的访问

格式:结构体变量名.成员名

iphone6.model;

iphone6.screen_size;

   ..结构体指针访问成员的格式

    (*p).成员

     p->成员

二:结构体初始化

结构体的初始化
 
     成员初始化的顺序必须和结构体定义的顺序一致
  
     1)定义的同时进行初始化
       
        形式一:
        struct Car{
            int lunzi;
            int speed;
            int zuweishu;
            char *pp;
        }bc={4,50,20,"奔驰"};
 
        形式二:
        struct Car bmw={3,200,200,"宝马X9"};
 
     2)先定义结构变量,在初始化
 
        struct Car ad;  //定义结构体变量
 
        ad.lunzi = 2;
        ad.speed = 10;
        ad.zuweishu = 1;
        ad.pp = "奥拓自行车";
 
 
     3)用结构体变量去初始化另外一个结构体变量
 
        struct Car byd;
        byd = bmw;  //用一个已知的结构体变量初始化另外一个结构体 
// 这里是值的传递,不是地址的传递 4)部分初始化 struct Car jac={.pp="江淮"}; 5)容易犯的错误

注意:结构体的赋值是值传递非地址传递

三:结构体的存储细节

结构体数据的对齐

根据一个模数,每次分配或者读取模数倍数的字节

模数如何取得?

结构体成员中内存占用字节数最大的的数,就是模数

结构体存储空间如何计算?

 //指定对齐的模数
    #pragma pack(2)
    
    struct A{
        int a;
        char c;
        char c1;
        int b;
    };
    
   printf("%ld\n",sizeof(struct A));
    //模数  4
    struct B{
    
        char c1[13];  //4        16  --->3
        char c2[21];  //5        20
        int b;        //1        4

    };

四:结构体的作用域

结构体的作用域和变量的作用域类似

分类:

全局结构体:在函数的外部定义的 结构体

定义开始 ------ 文件结束

可以在从定义向下的各函数中使用

局部结构体:在函数的内部定义的结构体

定义开始 ------ 函数的代码块结束"}"

不能在函数的外部使用局部结构体

五:结构体数组

结构体数组:

数组的每个元素都是一个相同类型的结构体变量

结构体数组的定义:

1)声明结构体的时候定义

struct Student{

char *name;

char sex;

float score;

}stu[4]; //定义一个结构体数组

2)使用已有的结构体定义数据

struct Student s[3]; //定义一个结构体的数组,每个元素都是一个Student类型的数据

结构体数组的初始化:

1)定义数组的同时,进行初始化

struct Student{

char *name;

char sex;

float score;

}s[2]={{"sb",'F',59.9f},{"cgx",'M',60.0f}};

2)先定义结构体,再声明数组,在初始化

struct Student s1[2]={{"sb",'F',59.9f},{"cgx",'M',60.0f}

3) 先定义数组,在初始化

struct Student s2[2];

s2[0]={"sb",'F',59.9f};

s2[1]={"cgx",'M',60.0f};

//1、第一种初始化方法
    struct Student{
        
        char *name;
        char sex;
        float score;
        
    }s[2]={{"sb",'F',59.9f},{"cgx",'M',60.0f}};
    
    for (int i=0; i<2; i++) {
        printf("姓名:%s,性别:%c,成绩:%f\n",s[i].name,s[i].sex,s[i].score);
    }
    printf("\n\n");
    //2、第二种初始化方法
    struct Student s1[2]={{"sb",'F',59.9f},{"cgx",'M',60.0f}};
    for (int i=0; i<2; i++) {
        printf("姓名:%s,性别:%c,成绩:%f\n",s1[i].name,s1[i].sex,s1[i].score);
    }
    printf("\n\n");
    //3、第三种初始化
    struct Student s2[2];
    s2[0]=(struct Student){"sb",'F',59.9f};
    s2[1]=(struct Student){"fengjie",'M',60.0f};
    for (int i=0; i<2; i++) {
        printf("姓名:%s,性别:%c,成绩:%f\n",s2[i].name,s2[i].sex,s2[i].score);
    }
    
    //4、指定成员的初始化
    struct Student s3[2];
    s3[0].name = "zbz";
    s3[1].name = "zxt";

六:结构体指针

结构体指针:

指向结构体变量的指针

结构体指针变量的定义:

struct Student{

char *name;

float score;

};

//定义一个指向结构体(Student)变量的值真

struct Student *p;

//定义结构体变量

struct Student stu1

结构体指针的初始化

1)定义的同时进行初始化

2)先定义,后初始化

p = &stu1;

结构体指针的访问

1)(*p).name

2) p->name(用指针访问结构体成员)

以上两种方法都可以

结构体 结构体变量 结构体指针 结构体数组

结构体:

struct Car{

//结构体成员

char sex;

};

//结构体变量

struct Car bmw;

//结构体指针

struct Car *p;

//结构体数组

struct Car car[5];

//局部的结构体
    struct Student{
        
        char *name;
        float score;
        
    };
    
    //定义一个指向结构体(Student)变量的值真
    struct  Student *p;
    
    //定义结构体变量
    struct  Student stu1;
    //stu1结构体变量,初始化
    stu1.name = "sb";
    stu1.score = 59.9;
    //stu 访问属性--->直接访问
    printf("%s,%f\n",stu1.name,stu1.score);
    
    //给结构体指针初始化
    p = &stu1;  // &取地址

    //使用指针变量p间接的访问stu1
    (*p).name = "zbz";
    (*p).score = 58;
    
    printf("%s,%f\n",(*p).name,(*p).score);
    
    struct Student *p1;
    p1 = p;   //地址的赋值,p1和p都指向同一块内存区域
    (*p1).name = "cgx";
    (*p1).score = 57;
    printf("%s,%f\n",(*p1).name,(*p1).score);
    printf("%s,%f\n",p1->name,p1->score);

七:结构体嵌套

/*
 嵌套结构体
 
   在定义结构体的时候,它的成员又是一个结构体变量(不是自己的结构体变量)
 
 嵌套结构体的初始化:
 
 
 
 
 
 
 */


#include <stdio.h>

//定义时间的结构体
struct Time{

    int hour;
    int min;
    int second;

};

//定义日期的结构体
struct Date{

    int year;
    int month;
    int day;
    struct Time time;


};


struct Employer{

    char *name;
    int age;
    char sex;
    //结构体的嵌套定义
    struct Date inDate;//是一个构造类型变量
    struct Date goDate;
    //结构体定义的时候,不能嵌套自己的结构体变量
    //struct Employer xiashu;

};

int main(int argc, const char * argv[])
{

    //对嵌套的结构体进行赋值
    struct Employer zbz={"zbz",28,'F',{2014,10,23,{12,12,12}},{2014,10,25,{11,11,11}}};
    char *fm="姓名:%s,年龄:%d,性别:%c,入职时间:%d-%02d-%02d %02d:%02d:%02d,离职时间:%d-%02d-%02d %02d:%02d:%02d\n";
    //对嵌套的结构体进行访问
//    printf(fm,zbz.name,zbz.age,zbz.sex,zbz.inDate.year,zbz.inDate.month,zbz.inDate.day,zbz.goDate.year,zbz.goDate.month,zbz.goDate.day);
    
    struct Employer *p;
    //定义结构体的指针
    p = &zbz;
    printf(fm,p->name,p->age,p->sex,p->inDate.year,p->inDate.month,p->inDate.day,p->inDate.time.hour,p->inDate.time.min,p->inDate.time.second,p->goDate.year,p->goDate.month,p->goDate.day,p->goDate.time.hour,p->goDate.time.min,p->goDate.time.second);
    
    return 0;
}

结构体类型一般可用在数据结构中链表,栈,队列中节点的定义

八:结构体和函数的关系

1>将结构体成员属性或者结构体变量作为参数传递给函数作为函数的形参(值传递)

2>将结构体变量的地址传递给函数作为函数的形参(地址传递,利用指针改变结构体属性成员)

  

#include <stdio.h>
struct Car{

    int lunzi;
    int speed;
    char *pp;

};

int  sum(int x,int y){
    return  x+y;
}

void changeCar(struct Car c1){
    c1.lunzi = 80;
    c1.pp="火车";
}
void changCar2(struct Car *pCar){

//    (*pCar).lunzi = 100;
//    (*pCar).pp = "火车";
    
    pCar->lunzi = 100;
    pCar->pp = "火车";
}
int main(int argc, const char * argv[])
{

    
    struct Car car={3,15,"时风"};
    struct Car car1={4,250,"永久"};
    
    //1、用结构体的成员作为函数的参数,是值传递
    int s = sum(car.lunzi,car1.lunzi);
    printf("两个车一共:%d轮子\n",s);
    
    //2、结构体变量作为函数的参数
    //  用结构体变量名作为函数的参数,还是值传递
    changeCar(car1);
    printf("%s,%d\n",car1.pp,car1.lunzi);  //永久 4
    
    //定义一个结构体的指针
    struct Car *p;
    p = &car1;
    
    changCar2(p);
    printf("%s,%d\n",car1.pp,car1.lunzi);  //火车 100
    
    return 0;
}

九: 枚举类型:

格式:enum 枚举名{枚举元素};

注意:枚举类型不是一个构造类型,因为它的每一个元素都不能再分解了

enum weedday{ri,yi,er,san,si,wu,liu};

enum iColor{jin,hei,hui,bai};

规范:

枚举元素的规范:k枚举类型名枚举值

enum Sex{kSexF,kSexM,kSexWeizhi};

枚举变量定义

枚举变量:

enum Sex s1; //s1就是一个枚举变量

enum Sex1{kSexF,kSexM,kSexWeizhi}s2,s3;

enum{kSexF,kSexM,kSexWeizhi}s4,s5;

枚举变量的初始化

s1=kSexF;

用枚举值来初始化把枚举变量

枚举元素值的问题

枚举类型的各元素初始化值

0 1 2

enum{kSexF,kSexM,kSexWeizhi}s4,s5;

枚举元素可以在定义的时候进行初始化

当某一个元素被初始化以后,后面的元素额值,会在前一个元素的基础上+1

3 4 5

enum{kSexF=3,kSexM,kSexWeizhi}s4,s5;

0 1 2 3 4 5 6

enum weedday{ri,yi,er,san,si,wu,liu};

0 1 5 6 7 8 9

enum weedday{ri,yi,er=5,san,si,wu,liu};

 结构体跟枚举在oc中是经常见到的类型需要注意