9.1 定义和使用结构体变量

9.1.1 自己建立结构体类型

C语言允许用户自己建立由不同类型数据组成的复合型数据结构,它称为结构体。

struct Student
{
int num;
char name[20];
char sex;
int age;
float age;
float score;
char addr[30];
};                    

/*
struct是声明结构体类型的关键字,不能省略。
*/

声明一个结构体类型的一般形式为:

struct 结构体名

​ {成员列表};

注意:

1.结构体类型的名字是由一个关键字struct和结构体名组合成的(例如:struct Student)

2.结构体名,如:Student(结构体名又叫结构体标记)

3.花括号内的子项,称为结构体成员,对成员都应进行类型声明

4.结构体类型可以有多种,成员可以属于另一个结构体类型。

struct Date
{
int month;
int year;
int day;
};

struct Student
{
int num;
char name[20];
char sex;
int age;
float age;
float score;
char addr[30];
struct Date birthday;            //成员birthday属于struct Date类型
}

模型图

结构体模型图.png

9.1.2 定义结构体类型变量

结构体被定义声明后,没有使用,系统对之不分配存储单元。

定义结构类型变量:

  1. 先声明结构体类型,再定义该类型的变量

    如:struct Student(结构体类型名) student1,student2(结构体变量名);

    定义结构体变量后,系统会为之分配内存单元。

  2. 在声明类型的同时定义变量

    struct Student
    {
    int num;
    char name[20];
    char sex;
    int age;
    float age;
    float score;
    char addr[30];
    } student1,student2;
    /*
    在写大程序时,往往要求对类型的声明和对变量的定义分别放在不同的地方,以便程序结构清晰,便于维护,一般不采用这种方式。
    */
  3. 不指定类型名而直接定义结构体类型变量

    一般形式:

    struct
    {
    成员列表
    } 变量名列表;
    /*
    说明:
        1.结构体类型和结构体变量是不同的东西,只能对变量赋值,在编译时,只对变量分配空间。
        2.结构体类型成员名可以与程序中变量名相同
        3.结构体变量中的成员,可以单独使用,作用相当于普通变量
    */
    

9.1.3 结构体变量的初始化和引用

在定义结构体变量时,可以对它初始化,即赋予初始值,然后引用这个变量。

# include "stdio.h"
int main ()
{
    struct Student            //定义声明结构体Student
    {
    int num;
    char name[20];
    char sex;
    char addr[30];
    };
    struct Student stu={101,"ahuang",'W',"123 Beijing Road"};//进行初始化赋值
    printf("No.:%d\nname:%s\nsex:%c\naddr:%s\n",stu.num,stu.name,stu.sex,stu.addr);
    return 0;
}


/*
1. 进行初始化时,初始化列表使用花括号括起来的一些常量。
    C99标准允许对某一成员初始化。如:
    struct Studnet stu={.name="xiehuangbao"};
    其他数值型被初始化为0,字符型被初始化为'\0',指针变量被初始化为NULL
2. 可以引用结构体变量中的值,引用方式:结构体变量名.成员名
    如:stu.num=10001;//在程序中对变量的成员赋值。
    .  是成员运算符,它在所有运算符中优先级最高,因此可以把stu.num作为一个整体看待,相当于一个变量
    注意:不能通过输出结构体变量名输出结构体变量所有成员的值
3. 如果成员本身又是一个结构体类型,则要用若干个成员运算符,一级一级找到最低的一级的成员。只能对最低级的成员进行赋值或存取以及运算。
    stu.num            //访问stu成员num
    stu.birthday.month    //访问stu成员中的成员month
4. 对结构体变量的成员可以向普通变量一样进行各种运算(根据其类型决定可以进行的运算)。
5. 同类的结构体变量可以进行相互赋值,如:
    stu1=stu2
6. 可以引用结构体变量成员的地址,也可以引用结构体变量的地址。例如:
    scanf("%d",&stu.num);    //输入&stu.num的值
    printf("%o",&stu);        //输出结构体变量&stu的首地址

    scanf("%d,%s,%c,%d,%f,%s\n",&stu);//不能用这样的语句读入结构体变量
    结构体变量的地址主要用作函数参数,传递结构体变量地址。
*/
# include "stdio.h"
/*
定义和使用结构体 
*/
int main()
{
    struct Student{        //定义和声明结构体Student 
        int num;//学号
        char name[20];
        float score; 
    };

    struct Student stu1,stu2;

    scanf("%d%s%f",&stu1.num,stu1.name,&stu1.score);
    scanf("%d%s%f",&stu2.num,stu2.name,&stu2.score);

    if(stu1.score>stu2.score) printf("%d\t%s\t%f\n",stu1.num,stu1.name,stu1.score);
    if(stu1.score<stu2.score) printf("%d\t%s\t%f\n",stu2.num,stu2.name,stu2.score);
    if(stu1.score=stu2.score) 
    {
        printf("%d\t%s\t%f\n",stu1.num,stu1.name,stu1.score);
        printf("%d\t%s\t%f\n",stu2.num,stu2.name,stu2.score);
    }
    return 0; 
 } 

9.2 使用结构体数组

9.2.1 定义结构体数组

# include "stdio.h"
# include "string.h"
/*
    定义和引用结构体数组 
*/
int main()
{
    struct Person            //声明结构体 struct Person 
    {
        char name[20];
        int count;
    };

    struct Person leader[3]={            //定义结构体数组并初始化 
        "Li",0,"Zhang",0,"Sun",0
    };

    int i,j;
    char lead_name[20];
    for(i=1;i<=10;i++)
    {
        scanf("%s",lead_name);
        for(j=0;j<3;j++)
        if(!strcmp(lead_name,leader[j].name))leader[j].count++;
    }
    for(i=0;i<3;i++)
        printf("%s\t%d\n",leader[i].name,leader[i].count);
    return 0; 
}

说明:

1.定义结构体数组一般形式是

  • struct 结构体名{成员列表} 数组名[数组长度];
  • 先声明一个结构体类型,再用此类型定义结构体数组;

2.对结构体数组初始化的形式是在定义数组的后面加上:={初值列表};

​ 如:

​ struct Person leader[3]={ //定义结构体数组并初始化
​ “Li”,0,”Zhang”,0,”Sun”,0
​ };

9.2.2 结构体数组的应用举例

# include "stdio.h"
# include "string.h"
/*
    定义和引用结构体数组 
*/
int main()
{
    struct Student            //声明结构体 struct Person 
    {
        int num;
        char name[20];
        float score;
    };

    struct Student stu[5]={            //定义结构体数组并初始化 
        10101,"Zhang",78,
        10103,"Wang",98.5,
        10106,"Li",86,
        10108,"Ling",73.5,
        10110,"Sun",100
    };

    struct Student temp;//临时交换存储变量 

    int i,j;

    for(i=0;i<=5-1;i++)
        for(j=i;j<5;j++)
        {
            if(stu[i].score>stu[j].score)
            {
                temp=stu[i];
                stu[i]=stu[j];
                stu[j]=temp;
            }
        }
    for(i=0;i<5;i++)
        printf("%d\t%d\t%f\n",stu[i].num,stu[i].name,stu[i].score);
    return 0; 
}

说明:

  1. 在定义结构体数组进行初始化时,将每个学生的信息用一对花括号包起来,这样做,阅读和检查比较方便。(提供程序的可读性)
  2. 注意临时变量temp定义为struct Student类型,只有同类型的结构体变量才能互相赋值,不必人为指定一个一个成员互换,这体现了结构体类型的好处。

9.3 结构体指针

9.3.1 指向结构体变量的指针

指针变量的基类型必须与结构体变量的类型相同。

例如:struct Student *p;

# include "stdio.h"
# include "string.h"

/*
    了解什么是指向结构体变量的指针变量以及 
    怎么使用该类型的指针变量 
*/
int main()
{
    struct Student
    {
        int num;
        char name[20];
        char sex;
        int age;
    };
    struct Student stu,* p;
    p=&stu;
    stu.num=10101;
    strcpy(stu.name,"LiLin");
    stu.sex='M';
    stu.age=25;
    printf("No.:%d\nname:%s\nsex:%c\nage:%d\n",stu.num,stu.name,stu.sex,stu.age); 
    printf("No.:%d\nname:%s\nsex:%c\nage:%d\n",(*p).num,(*p).name,(*p).sex,(*p).age);
    return 0;
 } 
/*
如果一个p指向一个结构体变量stu,以下3种方法等价:
1.stu.成员名(如:stu.num);
2.(*p).成员名((*p).num);
3.p->成员名(如p->num).        ->称为指向运算符
*/

9.3.2 指向结构体数组的指针

# include <stdio.h>
# include <string.h>
/*
    初步了解指向结构体数组的指针 
*/
int main()
{
    struct Student{
        int num;
        char name[20];
        char sex;
        int age;
    };
    struct Student stu[3]={
        {10101,"LiLin",'M',18}
       ,{10102,"ZhangFang",'M',19}
       ,{10103,"WangMin",'F',20}
    };                //定义结构体数组并初始化 

    struct Student *p;
    for(p=stu;p<stu+3;p++)    //使指向stu数组的第一个元素 
        printf("%d\t%s\t%c\t%d\n",p->num,p->name,p->sex,p->age);
    return 0;
}

/*
注意:
1.程序定义了p是指向struct Student类型的指针变量,它用来指向一个struct Student类型的对象,但是不能指向stu数组元素中的某一成员。
2.如果要将某一成员地址赋值给p,可以使用强制类型转换。如:p=(struct Student *)stu[0].name;
*/

9.3.3 用结构体变量和结构体变量的指针作函数参数

将一个结构体变量的值传递给另一个函数,有3种方法:

  1. 用结构体变量的成员作参数
  2. 用结构体变量作实参。结构体作实参时,采取的也是值“传递方式”,形参也必须是同类型的结构提提变量。在函数调用期间形参也要占用内存单元。这种传递方式在空间和时间上开销较大,且因采用值传递的方式,如果在执行期间,形参改变的haul,该值是无法返回给主调函数的,这往往造成使用上的不便。
  3. 用指向结构体变量的指针作实参。传递地址(推荐:减少内存开销,避免用结构体作实参的缺陷)。
# include "stdio.h"
# include "string.h"
# include "stdlib.h" 
/*
    了解和使用结构体变量和结构体指针作函数参数 

    有结构体变量,成员是学号,姓名,3门课成绩。输出平均成绩最高的学生信息 
*/ 
# define N 3 //定义有3个学生 
struct Student{
        int num;
        char name[20];
        float score1;
        float score2;
        float score3;
        float aver;
    }; 

int main ()
{
    struct Student stu[N],*p,student;
    int i=0;
    void input_information(struct Student *p);
    struct Student * max_aver(struct Student stu[]);
    p=stu;//指向首个元素 
    input_information(p);     //输入学生数据 
    for(;i<N;i++)            //输出输入的学生信息 
        printf("%d\t%s\t%f\t%f\t%f\t%f\t\n",stu[i].num,stu[i].name,stu[i].score1,stu[i].score2,stu[i].score3,stu[i].aver);
    p=max_aver(p);
    printf("%d\t%s\t%f\t%f\t%f\t%f\t\n",p->num,p->name,p->score1,p->score2,p->score3,p->aver);//输出最高平均学生信息 
    return 0;
}

void input_information(struct Student *p)
{
    int i=0;
    for(;i<N;p++,i++)
    {
        printf("请输入学生信息:\n");
        scanf("%d%s%f%f%f",&(p->num),&(p->name),&(p->score1),&(p->score2),&(p->score3));
        p->aver=(p->score1+p->score2+p->score3)/3;
    }

}

struct Student * max_aver(struct Student stu[])
{
    int i=0;
    struct Student * student;
    for(;i<N-1;i++)
        if(stu[i].aver>stu[i+1].aver)
            student=&stu[i];
        else
            student=&stu[i+1];
    return student;
}

9.4 用指针处理链表

9.4.1 什么是链表

链表是一种常见的重要的数据结构。它是动态的进行存储分配的一种结构。

链表根据需要开辟内存单元。

链表有一个“头指针”变量,它存放一个地址,该地值指向一个元素。链表中每个元素称为“结点”

每个结点应该包括两个部分:

  1. 用户需要用的实际数据;
  2. 下一个结点的地址。最后一个元素的地址部分存放NULL表示链表到此结束

链表元素在内存中的地址可以是不连续的。

找一个元素,必须知道上一个元素存放该元素的地址。没有头指针整个链表无法访问。

链表必须利用指针变量才能实现。一个姐弟啊应包含一个指针变量,用它存放下一个结点的地址。

/*
可以设计这样的结构体类型
*/

struct Student
{
int num;
float score;
struct Student * next;   //next是指针变量,指向结构体变量(即下一个元素地址)
};

/*
num和score   是存放的实际数据
next  是下一个元素地址

一个指针类型的成员既可以指向其他类型的结构体数据,也可以指向自身所在的结构体类型的数据。
*/

9.4.2 建立简单的静态链表

# include "stdio.h"
/*
建立简单的静态链表 
*/
int main ()
{
    struct Student            //定义声明一个结构体 
    {
        int num;
        float score;
        struct Student * next;    
    };

    //定义结构体变量以及指针变量 
    struct Student stu1,stu2,stu3,*p1,*p2,*head; 
    p1=&stu2;
    p2=&stu3; 

    //进行赋值操作
    stu1.num=10101;
    stu1.score=56.5;
    stu1.next=p1;

    stu2.num=10310;
    stu2.score=66.5;
    stu2.next=p2;

    stu3.num=10102;
    stu3.score=55.0;
    stu3.next=NULL;

    //没有头指针,链表无法访问
    head=&stu1; 
    do
    {
        printf("%d\t%f\n",head->num,head->score);
        head=head->next;
    }while(head!=NULL);

    return 0; 
} 
/*
head头指针指向stu1,stu.next指向了stu2,stu2.next指向stu3,stu3.next=NULL表示这个末尾元素,每个元素中都有实际数据,且每个元素中都有下一个元素地址,这就形成了简单的链表关系


静态链表:结点是在程序中定义的,不是临时开辟的,也不能用完后释放。
*/ 

9.4.3 建立动态链表

动态链表是指在程序执行过程中建立一个链表

# include "stdio.h"
# include "stdlib.h"

/*
    建立动态链表 
*/

struct Student            //定义声明一个结构体 
    {
        int num;
        float score;
        struct Student * next;    
    };

int main ()
{
    struct Student * pt;
    struct Student * creat();
    pt=creat();
    printf("%d\t%f\n",pt->num,pt->score);
    return 0; 
} 

struct Student * creat()
{
    struct Student *head,*p1,*p2;
    head=NULL;//先使头指针指向空 ,表示现在的链表是个空链表 
    int n=0;//表示结点个数
    p1=p2=(struct Student *)malloc(sizeof(struct Student));//开辟第一个结点,将地址赋值给p1,p2
    printf("请分别输入学号和成绩:\n");
    scanf("%d%f",&p1->num,&p1->score);//输入实际数据 
    while(p1->num!=0) 
    {
        n+=1;
        if(n==1)
            head=p1;//表示创建一个新的链表。 当n==1时 
        else{
            p2->next=p1;//存放下个结点的地址 
        }
        p2=p1;//指向同一个结点 
        p1=(struct Student *)malloc(sizeof(struct Student));//开辟新的结点 
        printf("请分别输入学号和成绩:\n");
        scanf("%d%f",&p1->num,&p1->score);//输入实际数据 
    } 
    p2->next=NULL;//没有创建结点,表示表尾 
    return head;
}

9.4.4 输出链表

将链表中各结点的数据依次输出。

# include "stdio.h"
# include "stdlib.h"

/*
    建立动态链表 
*/

struct Student            //定义声明一个结构体 
    {
        int num;
        float score;
        struct Student * next;    
    };

int main ()
{
    struct Student * pt;
    struct Student * creat();
    void printf_linked_list(struct Student * head);
    pt=creat();
    printf_linked_list(pt);
    return 0; 
} 

struct Student * creat()
{
    struct Student *head,*p1,*p2;
    head=NULL;//先使头指针指向空 ,表示现在的链表是个空链表 
    int n=0;
    p1=p2=(struct Student *)malloc(sizeof(struct Student));//开辟第一个结点,将地址赋值给p1,p2
    printf("请分别输入学号和成绩:\n");
    scanf("%d%f",&p1->num,&p1->score);//输入实际数据 
    while(p1->num!=0) 
    {
        n+=1;
        if(n==1)
            head=p1;//表示创建一个新的链表。 当n==1时 
        else{
            p2->next=p1;//存放下个结点的地址 
        }
        p2=p1;//指向同一个结点 
        p1=(struct Student *)malloc(sizeof(struct Student));//开辟新的结点 
        printf("请分别输入学号和成绩:\n");
        scanf("%d%f",&p1->num,&p1->score);//输入实际数据 
    } 
    p2->next=NULL;//没有创建结点,表示表尾 
    return head;
}

void printf_linked_list(struct Student * head)
{
    struct Student * pt;
    pt=head;
    if(head!=NULL)            //判断头指针是否为空,为空的话,链表无法访问
        while(pt!=NULL)
        {
            printf("%d\t%f\n",pt->num,pt->score);
            pt=pt->next;
        }
} 

9.5 共用体类型

9.5.1 什么是共用体类型

在同一个地址上,使用覆盖技术,后一个数据覆盖了前面的数据。这种使几个不同的变量共享同一段内存结构,称为“共用体”类型的结构。

共用体类型一般定义形式:

union 共用体名

{成员列表} 变量表列;

定义声明和定义变量与结构体相同。但是含义不一样:

共用体变量所占的内存长度等于最长成员的长度。

9.5.2 引用共用体变量的方式

必须先定义共用体变量,后引用。注意引用的是共用体的成员,不是共用体变量。

例如:

union Data        //声明定义一个共用体
{
int I;
char ch;
float f;
};

union Data a,b,c;    //用共用体类型定义变量

a.I                    //引用共用体成员,是正确的
a.ch
a.f

printf("%d",a);        //这样是错误的,不能引用共用体变量。
printf("%d",a.I);    //可以写成这样

/*
union        //这样也可以声明定义  
{
int i;
char ch;
float f;
}a,b,c;
*/

9.5.3 共用体类型数据的特点

使用共用体类型数据是要注意以下一些特点:

  1. 同一个内存段可以用来存放几种不同类型的成员。在每一瞬时,只能存放一个成员,也就是说,共同体变量只能存放一个值。

    union Date
    {
    int i;
    char ch;
    float f;
    };
    union Date a;
    a.i=97;
    //表示将整数97存放在共用体变量中,可以用以下输出语句:
    printf("%d",a.i);        //输出整数97
    printf("%c",a.ch);        //输出字符a
    printf("%f",a.f);        //输出实数0.000000
  2. 可以对共用体变量初始化,但初始化表中有一个常量。

    union Data
    {
    int i;
    char ch;
    float f;
    }a={1,'a',1.5};        //不能初始化3个成员,它们占用同一段存储单元
    union Data a={16};    //正确,对第一个成员初始化
    union Data a={.ch='j'};//C99允许对指定的一个成员初始化
  3. 共用体变量中起作用的成员是最后一次被赋值的成员,在共用体变量中的成员赋值后,原来变量存储单元中的值就被取代。

  4. 共用体变量的底子和它的各成员的地址都是相同的,因为共用同一块内存段。

  5. 不能对共用体变量名赋值,不能企图引用变量名来得到一个值。

    ​ C99允许同类型的共用体变量互相赋值。

    a=b; //a和b同类型的共用体变量,合法

  6. C99之前规定共用体变量不能作为函数参数,但可以使用指向共用体变量的指针作函数参数。C99允许共用体变量作函数参数。

  7. 共用体可以出现在结构体类型定义中,数组可以作为共用体成员。

什么时候会用到共用体呢?

处理数据是,有时需要对同一段空间安排不同的用途。

例如:

# include "stdio.h"
/*
共用体的简单使用场景 
*/

struct {
        int num;
        char name[10];
        char sex;
        char job;
        union
        {
            int clazz;
            char position[10];
        } category;
    }person[2];

int main()
{
    int i=0;
    for(;i<2;i++)
    {
        printf("请输入当前人的信息:\n");
        scanf("%d %s %c %c",&person[i].num,&person[i].name,&person[i].sex,&person[i].job);
        if(person[i].job=='s')//判断是学生还是老师
            scanf("%d",&person[i].category.clazz);//是学生输入相应的班级
        else if(person[i].job=='t')
            scanf("%s",person[i].category.position);//是老师的话,输入相应的职位
        else
            printf("输入信息有误\n"); 
    }
    for(i=0;i<2;i++)
    {
        if(person[i].job=='s')
            printf("%d\t%s\t%c\t%c\t%d\n",person[i].num,person[i].name,person[i].sex,person[i].job,person[i].category.clazz);
        if(person[i].job=='t')
            printf("%d\t%s\t%c\t%c\t%s\n",person[i].num,person[i].name,person[i].sex,person[i].job,person[i].category.position);
    }
    return 0;
 } 

9.6 使用枚举类型

一个变量只要几种可能的值,则可以定义为枚举类型。

枚举:把可能的值一一列举出来,变量值只限于列举出来的值的范围内。

例如:

enum Weekday {sun,mon,tue,wed,thu,fri,sat};

Weekday 是枚举变量

{枚举元素或是枚举常量}

声明枚举类型的一般形式为:

enum [枚举名]{枚举元素列表};

说明:

1.C编译对枚举类型的枚举元素按常量处理,故称为枚举常量

2.每个枚举元素都代表一个整数,C语言编译按定义时顺序默认它们的值为0,1,2,3…

例如: Weekday=mon; 相当于 Weekday=1;

3.枚举元素可以用来作判断比较。

下面我们用一个例子来介绍枚举类型的使用。

# include "stdio.h"
/*
简单了解枚举类型的使用
*/
int main()
{
    enum Color{red,yellow,blue,white,black};//定义枚举类型  枚举元素是常量 每个元素代表一个整数
    enum Color i,j,k,pri;//定义枚举变量
    int n=0,loop;//loop 是循环的层数
    for ( i = red; i <=black; i++)//第一次摸球
    {
        /* code */
        for ( j = red; i <=black; i++)
        {
            /* code */
            if (i!=j)
            {
                /* code */
                for(k=red;k<=black;k++)
                {
                    if (k!=i&&k!=j)
                    {
                        /* code */
                        n+=1;//开始统计有几中摸球方法数量
                        // printf("一共有%d摸球方法",n);
                        for ( loop = 1; loop <=3; loop++)
                        {
                            /* code */
                            switch (loop)
                            {
                            case 1/* constant-expression */:
                                pri=i;
                                /* code */
                                break;
                            case 2/* constant-expression */:
                                pri=j;
                                /* code */
                                break;
                            case 3/* constant-expression */:
                                pri=k;
                                /* code */
                                break;
                            default:
                                break;
                            }

                            switch (pri)
                            {
                            case  red/* constant-expression */:
                                printf("%-10s","red");/* code */
                                break;
                            case  yellow/* constant-expression */:
                                printf("%-10s","yellow");/* code */
                                break;
                            case  blue/* constant-expression */:
                                printf("%-10s","blue");/* code */
                                break;
                            case  white/* constant-expression */:
                                printf("%-10s","white");/* code */
                                break; 
                            case  black/* constant-expression */:
                                printf("%-10s","black");/* code */
                                break;   
                            default:
                                break;
                            }
                        }
                        printf("\n");
                    }
                }
            }

        }

    }
    printf("\ntotal:%5d\n",n);
    return 0;
}

/*
使用枚举常量red 和用0代表红,有什么区别,其实没啥问题。
使用枚举常量比使用常数的优点是更加直观,当出错时,更易于检查错误信息。
*/

9.7 用typedef声明新类型名

用typedef给新的类型名来替代已有的类型名。(给已有类型取别名)

有两种情况:

  1. 简单地用一个新类型名代替已有的类型名。

    如:typedef int Integer; //指定用Integer为类型名,作用与int相同

  2. 命名一个简单的类型名代替复杂的类型表示方法。

    • 命名一个新的类型名代表结构体类型

      typedef struct
      {
          int day;
          int month;
          int year;
      }Date;        //定义新类型名Date,代表上面的一个结构体类型。
      
      Date birthday;    //定义结构体类型变量,因为用typedef Date就是结构体的别名。
    • 命名一个新类型名代表数组类型

      typedef int Num[100]; //声明Num为整形数组类型名

      Num a; //定义a为整形数组名,它有100个元素

    • 命名一个类型代表指针类型

      typedef char * String; //声明String为字符指针类型

      String p,s[10]; //定义p为字符指针变量,s为字符指针数组

    • 命名一个新类型名代表只想函数的指针。

      归纳总结:声明新类型名的方法

      1. 按照定义变量方法写出定义体

      2. 将变量名换成新类型名

  3. 在最前面加关键字

    1. 用新类型名区定义变量

    注意:习惯上typedef声明的类型名第一个字母大写

  1. 以上方法实际上是为为特定的类型指定了一个同义字。

  2. 使用typeder只是给已有类型取了一个别名,并没有创造新类型

  3. typedef声明数组类型、指针类型、结构体类型、共用体类型、枚举类型,使得编程更加方便。

  4. typedef与#define表面上有相似之处。

    如: typedef int Count;

    ​ #define Count int;

    作用都是用Count代表int。

    1.#define是在预编译时完成的,只能做简单的字符串替换。

    2.typedef是在编译阶段处理的。并不是简单的字符串替换。例如:typedef int Num[10];Num a;并不是用Num[10]去替代int ,而是采用定义变量的方法那样先生成一类型名,然后用它去定义变量。

  5. 当不同源文件用到同一类型数据时,常用typedef声明一些数据类型。

  6. 使用typedef名称有利于程序的通用和移植。可以看书上的数据类型长度在不同编译器上不同的案例 p329。