A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王元18611727076 中级黑马   /  2015-10-29 19:35  /  1067 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

c-day8
//---------------------结构体
什么是结构体?
答:若干个相同或者不同类型的数据组成的新的类型

定义格式:
struct 结构体名{
   
    成员列表;   //格式: 类型 变量名;
   
};

//-----------------结构体变量
结构体变量特点:
一个复合类型,具备结构体的特性
struct Stu{
    int age;
}stu1,stu2;


//匿名结构体
struct{
    int model;
}s1; //


//先定义结构体,后定义变量
struct Stu stu3;


//------------------结构体变量中成员的访问方法

结构变量名.成员名

点语法
boy1.num             boy1的学号
boy2.sex             boy2的性别
boy1.birthday.month  boy1的生日的月份


//--------------------初始化结构体变量
初始化的时候,注意成员的顺序

1)定义的同时进行初始化
struct Stu{
    int age;
    char name[20];
    char *name2;
}stu1={23,"sss","xxx"};


2)定义结构体变量的同时初始化
struct Stu{
    int age;
    char name[20];
    char *name2;
}; //以上仅仅只是定义了结构体类型,还没有定义结构体变量

//定义结构体变量
struct Stu stu2 = {23,"sss","xxx"};

3)定义结构体类型同时定义结构体变量后初始化
struct Stu{
    int age;
    char name[20];
    char *name2;
}stu3;

stu3 = {23,"sss","xxx"};  //错误的

1.连续初始化
stu3 = (struct Stu){23,"sss","xxx"}; //正确


2.逐个初始化
stu3.age = 1;
strcpy(stu3.name,"xxx");   //为什么要使用strcpy这个方法,直接赋值可以吗?
stu3.name2 = "xxx";
//--------------------------------------------------

区分一个细节:
struct Stu{
    char name[20];        //字符串数组
    char *name2;          //字符串指针
}stu1;

stu1.name = "xxx" ;             //错误的
strcpy(stu1.name,"xxx");        //正确的  通过strcpy方法
stu1.name2 = "xxx"              //正确

//定义同时进行初始化  严格遵守定义顺序


//部分初始化
struct Stu{
    int age;
    char name[20];
};
方式一:struct Stu boy1={.name="weige"};
方式二:struct Stu boy1;
boy1.age = 10;


//-------------------结构体的数组
定义:由相同类型的结构体变量组成的有序的集合。

//----定义格式:
1) 定义结构体的同时定义结构体数组
struct Car{
    int lunzi;
    int speed;
}cars[5];

2) 使用匿名结构体定义数组
struct {
    int lunzi;
    int speed;
}cars[5];

3)先定义结构体类型,再定义结构体数组
struct Car{
    int lunzi;
    int speed;
};
struct Car cars[5];

//-------初始化:
1) 定义结构体数组的同时进行初始化
struct Car{
    int lunzi;
    int speed;
    char *name;
}cars[2]={{2,50},{80,300}};


2)方式二
struct Car{
    int lunzi;
    int speed;
    char *name;
};
struct Car cars[2]={{2,50},{80,300}};

3) 匿名
struct {
    int lunzi;
    int speed;
    int speed;
}cars[2]={{2,50},{80,300}};


4)先定义结构体数组,后初始化
struct Car{
    int lunzi;
    int speed;
    char *name;
}cars[3];
cars[0].lunzi = 4;
cars[0].speed = 200;
cars[0].name="xxxx";


通过数组角标整体去初始化 cars[1]=(struct Car){6,100};


//--------------结构体指针
定义:指向结构体的指针
格式:结构体类型 * 结构体指针变量名;
struct Student stu1;    //结构体变量
struct Student *pstu;   //结构体指针
pstu = &stu1;

作用:可以间接访问结构体变量中保存的成员变量值

(*pstu).name
(*pstu).sno 新的访问方法
pstu->name  // 只有结构体指针变量才可以
等价于 (*pstu).name


//-------------------结构体作用域
跟变量作用域用法一样  就近原则

//---------------------结构体存储空间
结构体在内存中占用的存储空间是 所有元素占用空间之和(考虑对齐)
1.逐个元素对齐(下个元素与之前所有元素之和对齐)
2.整体对齐(最后的和能单独整除所有元素)-->  最后能整除最长类型

//--------------共用体
union
联合体或共同体与结构体的区别---了解

1.联合体只能够存一个元素.里面有多个少元素的声名只是表示这块空间能够存这些类型的元素.结构体可以同时存在多个

2.联合体的字节总长度是里面能定义的最大字节数元素的长度.结构体是最大元素的倍数.


//结构体与数组有什么区别?
1.结构体可以存不同类型的元素,而数组只能存同一类型
2.结构体类型需要我们自已定义.数组是用别的类型加[元素个数]
3.结构体内存分配方式很特别,使用对齐原则,不一定是所有元素的字节数和,而数组一定是所有元素的字节数和.
4.结构体指针可以指针名->结构体元素名(取元素);数组不行.


union Person{
   
   
    int age;    4 + 4   8
   
    char *name;     //   地址都是占 8个字节   16
   
    float weight;  //体重   4 + 16  20+4
   
};


//-----------------枚举类型
使用场合:在开发中,如果一个变量只有有限的几个取值,可以使用枚举

1)枚举类型
enum <#枚举类型名#>{枚举值1,值2,值3,...};

2)枚举类型的变量

enum <#枚举类型名#>{枚举值1,值2,值3,...} <#枚举变量名#>;

举例:
enum Sex{kMan,kWomen,kYao}sex;
enum Sex s2;
匿名枚举:
enum {kMan,kWomen,kYao}s1;


3)枚举类型变量的使用
1)枚举元素的值
系统默认给枚举变量第一元素赋值为0,后面的元素依次是上一个元素+1

2)给枚举类型变量赋值
isex = man;
printf("%d\n",isex);


//-------------------typedef定义类型
定义:给已经存在的数据类型取一个别名
格式:typedef 原类型 新类型名; //新类型名尽量要大写

5.1、基本数据类型
typedef int  MALATANG;  别名: MALATANG

5.2、用在数组,给数组起别名
typedef int  ARRAY[5];  别名: ARRAY

5.3、给结构体其别名
typedef struct Person P;  别名: P
typedef struct { int screenSize; int ram;} IPHONE; 别名: IPHONE

5.4、给枚举类型起别名
typedef enum Sex{kSexMan,kSexWomen,kSexYao} iSex;  别名: iSex


//--------------------预处理指令的概念
定义:以“#” 开头的一些特殊的指令
作用:
在编译之前做些处理(宏定义,条件编译,文件包含)


常见的预处理指令: 宏

宏:特殊的标示符

宏替换 :在编译之前,在源文件中,所有出现宏名的地方 都用宏代表的字符串 去替换

注意:宏不是语句,不需要分号结束

//------------------文件包含
#include <>    导入系统头文件

#include ""    导入自定义头文件


相当于把.h头文件的声明 copy到当前

//--------------------宏定义
1)无参宏
#define 宏名 宏代表的字符串
#define M 10
#define AREA 3.14*M*M
#define PI 3.14

2)有参宏
#define Mi(y) y*y+3*y   // y 是形参,不分配空间,不需要写类型
#define MAX(a,b) a>b?a:b
#define SUM(a,b) a+b


#undef 宏名  结束此宏定义

习惯全大写或者k开头,使用的时候注意颜色


//------------------------条件编译
当条件满足的时候去编译一段代码
好处:可移植、生成更小的目标文件
格式:

//-------
#if     //必须判断的都是预处理指令

#elif

#else

#endif   //用完了记得要结束当前条件编译


//-------
#ifdef
#endif

//-------
#ifndef
#endif


//预防头文件重复包含
#ifndef __________头文件名_h
#define __________头文件名_h

/*在这里面放上你需要的代码*/

#endif


3 个回复

倒序浏览
赞一个.
回复 使用道具 举报
好好,分析的精辟
回复 使用道具 举报
厉害,大神 求带
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马