【黄色手套22】6话:构造数据类型

目录 

序言:

结构体:

结构体数组:

结构体数组的定义和引用 :

使用关键字typedef自定义类型名:

使用typedef语句为数组类型取别名:

结构体所占内存的大小:

结构体的嵌套:

共用体类型:

        共用体类型的声明:

        共用体变量的定义:

        共用体类型所占内存:

枚举类型:

        枚举类型的声明:

        枚举类型的使用:


序言:

构造数据类型:用户自己建立的数据类型(自定义数据类型)。

C语言中的构造数据类型有:数组类型、结构体类型、共用体类型和枚举类型。

结构体:

用户根据自己的需求建立的由不同类型数据组成的数据类型。

即,

结构体这种数据类型它能根据用户需要,方便的存储各种各样的信息。

■.  结构体类型的声明

(1)声明时定义结构体变量

struct 结构体类型名
{

        成员列表;

}结构体变量名;          // 可以在声明时定义结构体变量名
                       // 声明时未定义变量的话,分号(;)勿漏                    

(2)先声明后定义结构体变量

          基本格式:结构体类型名 变量名;

struct student s1;

//s1.id=12345;

■.  结构体成员的使用

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

     结构体成员引用符:.

     例如:

#include
struct pananzhongxue              //构造结构体,名为“pananzhongxue”
{
	int id;
	int age;
	float zongscore;
	int gender;
	char name[10];
}s1 = {085422103,19,536,1,"chenchen"}, s2;   //声明时定义结构体变量s1,s2,
                                             //并对s1初始化赋值
int main()                        
{                                   //输出“pananzhongxue”结构体类型中的s1的各个数据	                                    
	printf("%d\t%d\t%d\t%f\t%s\n", s1.id, s1.age, s1.gender, s1.zongscore, s1.name);                                           
	return 0;
}

说明:

(1) struct 为结构体关键字

(2)struct pananzhongxue 为结构体类型名

(3)idage... 为结构体成员名

(4)s1s2 为结构体变量

  区分清楚:结构体类型名、结构体成员名以及结构体变量

■.  结构体变量的定义:

  (1)可以在声明时直接定义结构体变量;

  (2)也可以先声明后定义结构体变量(用数据类型名定义结构体变量);

#include
struct pananzhongxue
{
	int id;
	int age;
	float zongscore;
	int gender;
	char name[10];
}s1, s2;                                 //声明时定义结构体变量s1,s2

int main()
{                                        //声明后定义结构体变量s3
	struct pananzhongxue s3 = {085422103,19,536,1,"xiaohei"};
	printf("%d\t%d\t%d\t%f\t%s\n", s3.id, s3.age, s3.gender, s3.zongscore, s3.name);
	return 0;
}

结构体数组:

结构体类型的数组

■.  结构体数组元素的使用:

结构体数组名[数组下标].成员变量名

  例如:

#include
struct student
{
	int id;
	int age;
	int height;
	int weight;
	float score;
}arr1[3];                  // 声明一个结构体数组arr1[3]

int main()
{
	arr1[0].id = 085422103;
	printf("%d\n", arr1[0].id);	
	return 0;
}

■.  注意数组类型的成员

  1. 数组类型int的成员,单个数据元素可以直接进行赋值:

#include
struct pananzhongxue
{
	int id;
	int age;
	float score[3];
	int gender;
	char name[10];
}s1, s2;

int main()
{	
	s2.age[0] = 15;             //数组类型单个数据元素赋值
	s2.age[1] = 11;
	s2.age[2] = 10;
	printf("%f\t%f\t%f\n", s2.age[0], s2.age[1], s2.age[2]);
	return 0;
}

2. 数组类型(如char)的成员不能直接赋值,

    可以用字符串拷贝函数strcpy来完成字符数组的赋值:

#include
#include               //输入字符串处理函数头文件
struct pananzhongxue
{
	int id;
	int age;
	float score;
	int gender;
	char name[10];
}s1,s2;

int main()
{
  strcpy(s1.name, "cc");      //用字符串拷贝函数strcpy来赋值
  printf("%s\n", s1.name);
  return 0;
}

■.  相同结构体类型的成员可以相互赋值:

#include
#include
struct pananzhongxue
{
	int id;
	int age;
	float score[3];
	int gender;
	char name[10];
}s1,s2;

int main()
{
	s2.score[0] = 105;
	s2.score[1] = 91;
	s2.score[2] = 110;
	
	s1.score[0] = s2.score[2];         //进行相互赋值
	s1.score[2] = s2.score[0];
	s1.score[1] = s2.score[1];

	printf("%f\t%f\t%f\n", s2.score[0], s2.score[1], s2.score[2]);
	printf("%f\t%f\t%f\n", s1.score[0], s1.score[1], s1.score[2]);
	return 0;
}

结构体数组的定义和引用 :

#include
struct student
{
   int id;
   char name[10];
};

int main()
{
   struct student arr1[2]={854221,"chenchen",854222,"chenhnch"};
   printf("id\tname\n);
   for(int i=0;i<2;i++)
  {
      printf("%d\t%s\n",arr1[i].id,arr1[i].name);
  }
  return 0;
}

使用关键字typedef自定义类型名:

关键字typedef:用于给数据类型关键字取别名

typedef的基本格式:

typedef 数据类型名 别名;

        typedef取的别名也需要遵循标识符的命名规则。 

        typedef可以给一个数据类型取多个别名

        typedef一般使用在数据类型名比较长的情况下

例如:

#include
typedef struct chenchenchenchenchen
{
	int height;
	int weight;
}xxx;

int main(void)
{ 
	xxx s1;                //取别名后需再定义结构体变量名
	s1.height = 172;
	printf("%d\n", s1.height);
	return 0;
}

使用typedef语句为数组类型取别名:

一维数组类型的定义格式:

typedef 数据类型 数组名[常量];

例如:

#include
typedef struct chenchenchenchenhcne
{
	int id;           
	char name[20];    
	char gender[4];   
	int age;          
	float score[3];   
}CC;

typedef int I[10];      // 定义了一个数组类型I  
                        // 元素类型为int
                        // 元素个数为10
int main(void)
{                                                
	I a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };       // 相当于int a[10]={...};  
                                                  // I换成a即可
	for (int i = 0; i < 10; i++)                  // 可多次定义对象(数组名)
	{
		printf("%d\t", a[i]);
	}
	putchar('\n');
	return 0;
}

结构体所占内存的大小:

计算结构体内存大小时要考虑其内存布局。

系统为了提高计算机访问数据的效率,

在安排结构体中的每个成员时采用内存对齐的方法。

结构体在内存中按统一单元进行存放,
每个单元的大小取决于结构体成员中最大的基本数据类型大小。

即,在结构体中,对不同成员类型的大小,在内存中采取内存对齐的方法以提高运行效率

例如:

#include
typedef struct student
{
	short id;      //2
	short age;     //2
	char name[5];  //5
	int height;    //4
	int weight;    //4 
	float score;   //4 
}xxx;

int main()
{
	printf("%d\n", sizeof(xxx));       //  24	
	return 0;
}

内存储存如下:

补充: 为什么要内存对齐?

1.为了提高代码的可移植性,和提升CPU访问内存的效率(本质:以空间换时间)。

2.不是所有的硬件平台都能访问任意地址上的数据,某些硬件平台只能在某些地址访问某些特定类型的数据,否则会抛出硬件异常,以及遇到未对齐的边界直接就不进行读取数据。 

结构体的嵌套:

把一个结构体的变量作为另一个结构体的成员。

例如:

#include
struct student
{
	int id;              
	int height;              
	int weight;          
	char gender[3];        
	char name[10];       
	float score[3];         
}s1,s2,s3;

struct teacher
{
	int id;              
	int height;              
	int weight;          
	char gender[3];        
	char name[10];       
	struct student s1;      // 结构体嵌套
}t1,t2,t3;                  // 结构体类型student中的变量s1是结构体类型teacher中的成员 
                            // teacher中的成员
int main()
{
	t1.s1.id = 85422103;
	printf("%d\n",t1.s1.id);
	return 0;
}

■.  注意,一个结构体类型中可以有本身这种结构体类型的成员吗?

struct teacher
{
	int id;              
	int height;             
	int weight;         
	char gender[3];        
	char name[10];       
	struct teacher t2;     //可以吗?
};

-----会报错:不允许使用不完整的类型。

共用体类型:

用同一段内存单元存放不同类型的变量。

同一个内存单元中,它们在内存中所占字节数不同,但共用同一段内存地址。

共用体类型的声明:

一般格式:

union 共用体类型名
{
  成员列表;
}共用体变量;

共用体变量的定义:

(1)声明时定义;

(2)声明后定义;共用体类型名 变量名;

例如:

#include
union student
{
	int id;
	float score;
	char a;
	double b;
}t1,t2;

int main()
{
	printf("%d\n", &(t1.id));         //所有输出结果相同
	printf("%d\n", &(t1.score));      //为共用内存的首地址 
	printf("%d\n", &(t1.a));
	printf("%d\n\n", &(t1.b));

	printf("%d\n", &(t1.b));          //下面也是一样的
	printf("%d\n", &t1.b);            //且每次运行会重新随机申请存储空间 
	printf("%d\n", &t1);
    return 0;
}

共用体类型所占内存:

整个共用体类型所占内存是最大成员所占的内存空间(或其整数倍)

例如:

#include
union student
{
	int id;             //4
	float score[10];    //4*10
	char a;             //1
	double b;           //8 
}t1,t2;

int main()
{
	printf("%d\n", sizeof(union student));  //8*5
    return0;
}

#include
union student
{
	int id;
	float score;
	char a;
	double b;
}t1,t2;

int main()
{
	printf("%d\n", sizeof(union student));  //8
    return 0;
}

注意:所占内存空间为最大基本数据类型的最小整数倍

例如:

#include
union student
{
	int id;
	float score;
	char a[10];
	double b;
}t1,t2;

int main()
{
	printf("%d\n", sizeof(union student));  //16
    return0;
}

存储和读取数据时:

#include
union student
{
	int id;
	float score;
	char a;
	double b;
}t1,t2;

int main()
{
    t1.id = 0x11223344;
	t1.a = 0x55;
	printf("%x\n",t1.id);      //11223355
    printf("%x\n",t1.a);       //55
	return 0;
}

大端模式:

                                                                       

共用体变量只能给一个成员初始化赋值,

共用体同一时刻只能保存一个成员的数据(数据相应位置覆盖)

枚举类型:

枚举类型enum:将类型中所有可能的取值一一列举出来,

             枚举值只能从列举出的范围内取值,

             否则没有意义。

枚举类型可以初步简单理解为取值受限的整型,其值被按照整型数据来处理和运算。 

如果一个变量只有几种可能的值,就可以定义为枚举类型。

枚举类型的声明:

enum 枚举类型名
{
   枚举元素列表;
}枚举类型变量名;

例如:

enum day{
    sun,mon,tue,wed,thu,fri,sat
}weekend,workday;

//声明了一个枚举类型,数据类型名day,
//其变量的取值范围为星期天至星期六,
//声明时定义了两个枚举类型变量weekend和workday。

注意:

声明的枚举类型也可以没有类型名,

但如果需要使用此枚举类型的话,就必须在声明时同时定义变量。

枚举类型的使用:

   C语言中的枚举元素是按照常量进行处理的,所以又称为枚举常量。

   不能因为它们是标识符而把它们当作变量来使用,在使用时是不能对它们赋值的。

sun=0;mon=1;//错误,不能给枚举常量赋值

   每一个枚举元素都代表一个整数,

   C语言编译器按照定义时的顺序默认它们的值为0,1,2,3,4,5,6......

workday=mon;//相当于workday=1;

   枚举常量的引用和输出:

   printf("%d",sun);   //输出整数0 

   枚举变量的引用和输出:

workday=mon;

printf("%d",workday);    // 输出整数1

  我们也可以人为的指定枚举元素的数值,在声明的枚举类型时指出即可。

  例如:

enum weekend{sun=7,mon=1,tue,wed,thu,fri,sat}weekend,workday;

// 星期二2,星期三3,......星期六6

  枚举类型可以用来进行比较和判断

if(workday==mon){......};

if(workday==sat){......};

  示例:

#include
enum weekday{sun=7,mon=1,tue,wed,thu,fri,sat};

int main()
{
	printf("%d %d %d %d %d %d %d\n", sun, mon, tue, wed, thu, fri, sat);
	return 0;
}
// 输出7 1 2 3 4 5 6

  简单的枚举类型应用示例:

  根据你输入的数字输出对应的星期数

#include
enum weekday{sun=7,mon=1,tue,wed,thu,fri,sat}day;

int main()
{
	while (1)
	{
		scanf("%d", &day);
		switch (day)
		{
		case 7:
			printf("你输入了周日\n");
			break;
		case 6:
			printf("你输入了周六\n");
			break;
		case 5:
			printf("你输入了周五\n");
			break;
		case 4:
			printf("你输入了周四\n");
			break;
		case 3:
			printf("你输入了周三\n");
			break;
		case 2:
			printf("你输入了周二\n");
			break;
		case 1:
			printf("你输入了周一\n");
			break;
		default:
			printf("你输入了无效数字\n");
		}
	}
	return 0;
}

_____________# 

你可能感兴趣的:(1:C语言,c语言)