数据类型的使用包括常量,变量和类型间的转换,同时笔者将数组的部分内容归纳在了这里。
(一)变量和常量
在前面曾提到过“每一种数据类型是对一类事物的描述,当描述某个具体事物时,就会定义一个变量来描述,每个变量都会占用一定的内存空间,比如前面描述基础数据类型时说的占用多少个字节”。其实,这里已经有了对变量概念的一个抽象性描述。
变量,是指在程序运行过程中值允许改变的量。常量,是指在程序运行过程中值不允许改变的量。
C语言里,每个变量/常量都会对应一种数据类型。
定义变量格式为[数据类型][空格][变量名]或者[数据类型][空格][变量名] = 初始值。
定义常量格式为 const [数据类型][空格][常量名] = 值。
程序运行中,常量值不能变更,变量值如果要变更,则使用“【变量名】= 新的值”进行赋值,如果要获取常量值或者变量值,则用赋值运算符 =,将值取出即可。参考下面一段代码。
int weight_of_A = 0;
int weight_of_B = 0;
const int weight_of_C = 70;
int total weight;
total_weight = weight_of_A + weight_of_B + weight_of_C;
weight_of_A = 99;
weight_of_B = 23;
total_weight = weight_of_A + weight_of_B + weight_of_C;
第一次total_weight计算结果是70,第二次total_weight计算结果是192。
对于结构体和联合体,需要使用 “.” 运算符来对成员进行对应值的读写。比如
STRU_STUDENT a;
Union_MultiDescription b;
int Class;
a.Class = 1;
b.student.Class = 2;
Class = a.uiClass;
Class = b.student.uiClass;
(二)数组
数组在C语言里是同一数据类型的一系列有序元素的集合。
比如一个班里有很多学生,现在要描述一个学生。我们可以定义STRU_STUDENT a,来用a来描述他。如果要描述两个学生,可以定义STRU_STUDENT a,b来描述。但是如果要描述一个班所有学生,这样定义情况就会变得非常糟糕。于是我们可以采用数组来描述。
#define STUDENT_NUM 48
STRU_STUDENT astruStudent[STUDENT_NUM];
这样我们要获取第一个学生就用astruStudent[0],第二个就用astruStudent[1]来获得就可以了。其中[num]中的数组叫做下标,C语言下标(数组索引)都是从0开始的。这里定义的是一维数组,数组支持多维定义,比如一个年级有五个班,每个班最多50个学生,那么就可以定义成
#define CLASS_NUM 5
#define STUDENT_NUM 48
STRU_STUDENT astruStudent[CLASS_NUM][STUDENT_NUM];
这样第一个班级的第一个学生就是astruStudent[0][0],第三个班级的第十个学生就是astruStudent[2][9]了。
(这里只是简单介绍数组定义和使用,更多的细节和知识点会在后续整理。)
(三)类型转换
类型转换是指数据在运算过程中类型发生了变换。C语言的类型转换分为强制类型转换和隐式类型转换。
强制类型转换是指运用强转方式将一片内存中按照一种数据类型存放的值强行按照另一种数据类型解读。
比如前面提到的联合体的多接口例子。
#define MAX_CHAR_NUM_OF_NAME 64
typedef enum ENUM_SEX {
ENUM_MALE,
ENUM_FEMALE
} ENUM_SEX;
struct STRU_STUDENT_PRIVATE {
char aucName[MAX_CHAR_NUM_OF_NAME]; // 姓名,字符型数组
ENUM_SEX enSex; // 性别,枚举
unsigned int uiAge; // 年龄,无符号整型
unsigned int uiGrade; // 年级,无符号整型
unsigned int uiClass; // 班级,无符号整型
};
#define PADDING_LEN_A (MAX_CHAR_NUM_OF_NUM + sizeof(ENUM_SEX) + sizeof(unsigned int))
struct STRU_STUDENT_MODULEA {
unsigned char aucPadding[PADDING_LEN_A]; // 填充段,对外显示为填充
unsigned int uiGrade; // 年级,无符号整型
unsigned int uiClass; // 班级,无符号整型
};
#define PADDING_LEN_B (sizeof(ENUM_SEX) + 3 * sizeof(unsigned int))
struct STRU_STUDENT_MODULEB {
char aucName[MAX_CHAR_NUM_OF_NAME]; // 姓名,字符型数组
unsigned char aucPadding[PADDING_LEN_B]; // 填充段,对外显示为填充
};
union LOCAL_PROC_Student {
struct STRU_STUDENT_PRIVATE inst_local;
struct STRU_STUDENT_MODULEA inst_for_a;
struct STRU_STUDENT_MODULEA inst_for_b;
};
STRU_STUDENT_PRIVATE student_local;
STRU_STUDENT_MODULEA student_A;
student_local.uiGrade = 1;
student_A = (STRU_STUDENT_MODULEA)student_local;//强制类型转换
这样操作之后,student_A.uiGrade的值就也是1了。
强制类型转换其实就是在使用前将数据转为目标数据类型,方式是在变量前使用”(目标数据类型)“来进行转换。
强制类型转换要谨慎使用,特别是C语言常常会有地址表,在将地址表中的地址转换为对应结构体的指针时需要万分小心。
隐式类型转换则是在运算过程中程序将遇到类型不匹配的数据类型且符合隐式转换规则的数据自动转换为统一的类型。
比如如下代码段就是一个隐式转换的例子。
char a = 1;
int b = 2;
int c;
c = a + b;//这里程序会自动将a的数据类型转化为int类型,然后和b相加赋值给c。
隐式转换有一个规则,一般是将占用内存少的数据类型向占用内存多的转换,低精度的向高精度的转换。下面是部分数据类型的转换规则的例子,箭头指向目标数据类型。
double ← float
↑
unsigned long long
↑
long long
↑
unsigned long
↑
long
↑
unsigned int ← int ← unsigned short ← short ← unsigned char ← char