原创 C语言中的结构、联合、枚举

2011-6-14 17:46 2961 10 10 分类: MCU/ 嵌入式

第九章  结构、联合、枚举<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

(用户定义数据类型)

一、用户定义数据类型概述

?      用户定义数据类型的特点

    类型标识符由用户自行定义

    用户定义的数据类型既可以是基本类型的操作数(例:枚举),也可以是包含多个不同类型不同长度数据的集合(例:结构)。

?      用户可定义的数据类型

  结构(struct:  构造类型

  联合(union :  构造类型

  枚举(enum  :  基本类型

第一节  结构类型

一、结构类型的定义

?      定义格式

      struct   类型名        ←类型标识符

 {  数据类型  成员名←成员的类型及名字

      。。。

  };     ←必须有分号

只定义了一种数据类型,不占用存储空间

例:

    struct  st     类型标识符是struct  st

{   long  id;              \*学号*\

    char  name[10];

    char  sex[2];        \*m:男,f:女 *\

    float  mark[3];   \*成绩*\

};

(1) 类型名、成员名应遵守标识符命名规则

(2) 同一结构中不允许出现同名的成员

(3) 成员的数据类型可以是任何已定义的数据类型(基本类型、构造类型、指针类型)

(4) 当成员是指针型变量或数组时,数据类型可以是正在定义的结构类型自身。例

  struct  st   

  {   long  id;

      char  name[10];

      char  sex[2];

      float  mark[3]; 

      struct  st  *next ;

   };

(5) 成员没有存储类型不能使用auto,register,

extern,static  ( C++中可以使用static )

(6) 数据类型的定义在源程序中的位置决定了所定义的数据类型标识符的作用域

  函数外:作用域为定义位置至文件结束

  函数内:作用域为定义所在函数

(7) 大型程序通常将大量结构类型的定义放在头文件中。

(8) 编译系统的头文件中包含了一些结构类型定义

二、结构型变量的声明和初始化

?      先定义数据类型后声明变量

(1) 变量声明格式

    存储类型  struct   类型名  变量名={初始值};

    存储类型可缺省。

    初始值可缺省。全局变量和静态局部变量无初始值时系统为全部成员置初值0。

 struct  st   s1,  s2={1,”Tom”,”m”,70,  80};

   变量s1所有成员初值不确定,s2的成员mark[2]为0

 static  struct  st  s3; 

   变量s3所有成员初值为0

说明:

(1) 变量名可以与该结构中某个成员同名

(2) 变量声明位置决定了结构变量的作用域

   函数外:全局结构变量

   函数内:局部结构变量 

?             在定义数据类型的同时声明变量

(1)  方式一

      struct st

 {  long id;

    char name[10], sex[2]

    float mark[3];

 }s1={1,”Tom”,”m”,70,80,90} , s2;

特点

    s1,s2的存储属性只能是缺省类型全局变量为extern局部变量为auto)。

    s1,s2的作用域由其定义和声明位置确定

 

(2) 方式二 

     struct

 {  long id;

    char name[10]

    char sex[2]

    float mark[3];

 } s1={1,”Tom”,”m”,70,80,90} , s2;

特点:

   没有定义类型标识符,不能再声明新变量。

   s1,s2的存储属性只能是缺省类

    s1,s2的作用域由其定义和声明位置确定

三、结构型变量的存储结构

       一个结构变量的所有成员按出现顺序占用一片连续存储区域的不同单元。

      struct

 {  long id;

    char name[10]

    char sex[2]

    float mark[3];

 } s1={1,”Tom”,”m”,70,80,90} , s2;

     变量s1占用的存储单元

      =4 (id) +10 (name) + 2 (sex)+12 (mark)  = 28  bytes

四、结构型变量的赋值与引用

?      类型相同时可直接引用结构型变量做赋值运算

  struct st   s1,  s2 ={1, ”Tom”,”m”};

  FILE   s3={0};

  int       s4=0;

  s1=s2;      (正确)

  s1=s3;      (错误)

     Illegal structure operation in function main

  s1=s4;      (错误)

    Illegal structure operation in function main

?      不能引用结构型变量做算术、关系、逻辑运算

   struct  st  s1={1,”Tom”,”m”},  s2={0},  s3;

      s1+s2   ,   s1++  , s1==s2 ,    s1 && s2   错误)

?       sizeof  运算可以得到一个结构变量的存储字节数

     int  y;  

     struct  st  s1;

     y=sizeof(s1);          y= sizeof(struct  st);

五、结构型变量成员的引用

?      引用格式

   结构变量名.成员名

    “.”为成员引用运算符,优先级最高。

  s2.id=s1.id;         (正确)    

  s2.name = s1.name     (错误)

  strcpy ( s2.name ,  s1.name);     (正确)

  s2.name[0] = s1.name[0]     (正确)   

 

判断s1是否等于s2的语句

    t =s1.id==s2.id&& strcmp(s1.name,s2.name)==0&&strcmp(s1.sex,s2.sex)==0&&s1.mark[0]==s2.mark[0] && s1.mark[1]==s2.mark[1]&&s1.mark[2]==s2.mark[2]  

    if (t)

    {  语句  }

六、结构型变量的输入输出

struct   st   s1;

scanf(“%ld%s%s%f%f%f”,  &s1 ); 

    只有s1的第1个成员获得输入的数据)

scanf(“%d%s%s”,  &s1.id,   s1.name,   s1.sex); 正确

for(j=0;j<3;j++)

scanf(“%f”,  &s1.mark[j]);      正确

七、嵌套结构类型

?      嵌套结构类型的定义( 方式一)

 struct date

{   int year,minth,day; };

 struct st

{  long  id;

    char   name[10], sex[2];

    struct date  birthdayregisterday;

    float mark[3];

};

?           嵌套结构类型的定义方式二

struct   st

{   long  id;

    char   name[10];

    char  sex[2];

    struct date

    { int  year, minth, day;} birthday registerday;

    float mark[3];

};

?      嵌套结构型变量的声明、引用与输入输出

 struct  st  s1={1,”Tom”,”f ”, {1980,2,12},  70, 80, 90 };

 static  struct  st  s2;

 s2.birthday={1982,2,12};                    错误

 s2.birthday.year =1982;                      正确

 s2.birthday.month = 2;                          正确

 s2.birthday.day = 12;                            正确

 scanf(“%d”,  &s2.birthday.year);        正确

 printf(“%d”,  s2.birthday.year);         正确

八、将局部结构型变量的值传给另一函数

  struct  comp {  double x ,  y;  }

 struct comp   cadd(struct comp c1, struct comp c2)

 {  struct   comp  c;

     c.x=c1.x+c2.x;   

     c.y=c1.y+c2.y;

    return c;

 }

main()

{ struct  comp  a1={1.2 , 2.3},  a2={2.3 , 3.4},  a3;

   a3=capp(a1,a2);

   printf(“%f,%f ”, a3.x,  a3.y ) ;

}

九、结构型数组

?      结构型数组的声明和初始化

 1

     struct  st   s1[100]={{1,”Tom”,”m”}, {2,”Mary”,”f”}};

struct  st   s2[10][10];

2

    struct st

{   long id;

    char  name[10],  sex[2];

    float  mark[3];

 }s1[100]= {{1,”Tom”,”m”}},  s2[10][10];

?             结构型数组元素的赋值和引用

(1) 直接引用数组元素(仅限于赋值操作)

  for(i=0;i<100;i++)

         s2=s1;

   只有当两个数组的数据类型完全相同时才是合法的

(2) 直接引用数组元素的成员

:      for(i=0;i<100;i++)

       {   s2.id=s1.id;

           for(j=0;j<3;j++)

                 s2.mark[j]=s1.mark[j];

         }

?      结构型数组的输入输出

:

 for(i=0;i<100;i++)

  {   scanf(“%d%s”, &s2.id,  s2.name);

      for(j=0;j<3;j++)  scanf(“%f”,  &s2.mark[j]);

  }

 输出函数调用类似

?       Tc2.0系统的特殊处理

     struct

 {  long id;

     float sum;

  }s[100];

      for(i=0;i<100;i++)

{ scanf("%f ",  &s.sum); }

以上程序段运行时若显示如下信息并终止程序运行:

scanf : floating point formats not linked

Abnormal program termination

解决方法

     float y;

     for(i=0;i<100;i++)

{    scanf("%f",&y);    s.sum=y; }

?      将局部结构型数组的指针传给另一函数

 void f (struct  st   x[ ] , int  n) 

形式参数声明struct  st   x[ ]  等同于  struct  st   *x

{  int i,j;

   for(i=0;i<n;i++)

   {   scanf(“%ld%s%s”, &x.id,  x.name,  x.sex);

       for(j=0;j<3;j++)  scanf(“%f”,  &x.mark[j]);

   }

}

键盘输入1   mary   f   88  77  90  .  .  .

 main()

{  struct  st  s1[10],  s2[100];

    f (s1,10);      f (&s1[0],10);

    f (s2+10 , 90 );  f( &s2[10] , 90);

}

?      嵌套的结构型数组

:

    struct date{  int year,month,day;};

    struct st

{  long id;

   char name[10],  sex[2];

   struct  date  date[2];     /*入学日期毕业日期*/

}s[100];

     for(i=0;i<100;i++)

 {   s.date[0].year=2003;       s.date[1].year=2007; }

第二节    联合类型

一、联合类型与结构类型的不同点

定义数据类型时使用的类型说明符不同

变量的存储结构不同

声明变量时初始值的个数不同

二、联合类型的定义

?      定义格式

 union  类型名

{  数据类型  成员名;

    。。。

} ;

      

 union  data

 {  int    i;

    char  ch[2];

    float  f;

 };

二、联合型变量的声明和初始化

?      声明格式

   存储类型   union 类型名  变量名=初始值;

    可缺省:存储类型,初始值

    若有初始值,只能有一个初值,该值的类型应与该联合类型中某个成员的类型相同。

 union  data  u1, u2 =32767;

 static union   data  u3, u4[100];

三、联合型变量的存储结构

    一个联合型变量的所有成员共用一块存储区域,该存储区域的字节数等于占用存储单元最多的成员所需要的字节数。

union  data

 {  int i;

    char  ch[2];

    float  f;

}u={32767};      

四、联合型变量成员的赋值与引用

?      引用格式(与结构变量相同)

变量名.成员名

:

   u.i=0x4241;

   printf(“%c,%c”, u.ch[0],  u.ch[1]);

输出:A , B

五、嵌入在结构中的联合型变量

 struct   date

{   int year,month,day; };

 union   employeedate

{   long worked_days;

    struct date  last_day;

};

 struct   employee

{  long id;

   char name[10];

   union   empdate  date;

} staff [100];

 staff[0].id=1; 

 strcmp(staff[0].name,”Tom”);

 staff[0].date.worked_days=1000;    在职雇员

 staff[1].id=2;

 strcmp(staff[1].name,”Mary”);

 staff[1].date.last_day.year=2004;    离职雇员

 staff[1].date.last_day.month=4;

 staff[1].date.last_day.day=4;          

第四节    枚举类型

一、枚举类型的特点

?      类型的值是整数

  (整数型:int,  char,  枚举)

?      int/char的不同之处

    int /char: 没有限定可用值的范围,只有可表示值的范围。

            枚举:限定了可用值的范围。

?      枚举类型可用值范围的每个整数均以符号常量形式定义。

二 、枚举类型的定义

?      定义格式

   enum 类型名

  { 枚举常量表 };

 enum  color {  RED, GREEN, BLUE  };

  类型标识符    枚举常量表

  枚举常量表中出现的常量等同于符号常量的作用 

?             定义枚举常量所代表的整数值的几种方式

(1) 所有枚举常量使用缺省值

      enum color{ RED, GREEN, BLUE };

      RED 代表0GREEN 代表1BLUE 代表2

(2) 为所有枚举常量指定特定的值

      enum color { RED=2GREEN=1, BLUE=0 };

(3)  部分枚举常量指定特定的值其它使用缺省值

      enum weekday

     { SUN=7, MON=1,TUE,WED,THU, FRI, SAT } ;

      TUE代表2WED代表3。。。SAT代表6

(4)  允许为多个枚举常量指定相同的值

      enum color { RED=1, GREEN=1, BLUE };

三、声明和引用枚举变量

?        变量声明的三种形式

   enum color  c1, c[10];

   enum color{RED,GREEN,BLUE } c1, c[10];

   enum{RED,GREEN,BLUE } c1, c[10];

?      枚举变量赋值

    用枚举常量表中给出的枚举常量给该类型枚举变量赋值

c1=RED;   c[0]=BLUE; 正确

         c1=0;   c[0]=3;              错误)

四、枚举变量输入输出

 

  scanf (“%d”, &c1 ); 

  printf (“%d”, c1 ); 

    直接输入输出的是枚举常量所代表的整型数,而不是枚举常量名。

五、使用枚举常量

 通过定义枚举类型而定义一组符号常量。

 例:在graphics.h中定义了代表16个颜色的符号常量

enum COLORS {

    BLACK,             /* dark colors */

    BLUE,

    GREEN,

    CYAN,

    RED,

    MAGENTA,

    BROWN,

    LIGHTGRAY,

    DARKGRAY,            /* light colors */

    LIGHTBLUE,

    LIGHTGREEN,

    LIGHTCYAN,

    LIGHTRED,

    LIGHTMAGENTA,

    YELLOW,

    WHITE

};

调用设置前景颜色函数:  setcolor(BLUE);    等同于    setcolor(1);

第五节       typedef

?      typedef的功能

  为已定义的数据类型定义一个新的类型说明符。

例1:

 定义类型说明符:

  typedef    unsigned   long   int    ULINT ;

  typedef  struct

  {  long id;   char  name[10],  sex[2]; } PERSON;

  typedef  enum { TRUE=1, FALSE=0 } BOOL;

应用类型说明符:

 ULINT  k,j;

 PERSON  S[100];

 BOOL  t;

例2:

定义类型说明符:

 typedef  int  IARR1[10];   int [10]代表一维数组类型

 typedef  int  IARR2[3][4]; int [3][4]代表二维数组类型

 typedef  int  *  IP;              int * 代表指向int数据的指针类型

应用类型说明符:

  IARR1  a,b;    声明 a,b为一维数组

  IARR2  c,d;    声明c,d为二维数组

  IP  p1,p2;        声明p1,p2为指向int数据的指针变量

文章评论0条评论)

登录后参与讨论
我要评论
0
10
关闭 站长推荐上一条 /2 下一条