【C 语言入门】数据类型
C 语言的数据类型
数据类型,即数据对象的类型,是编程语言的基石。自编程语言发明以来,数据类型就已经存在,其最初的目的就是为了能够让程序更加充分的利用稀缺的内存空间。
在硬件行业严格遵守摩尔定律发展了多年后的今天,开发者得以享受充足内存资源,同时,数据类型也被赋予了更深厚的含义:
- 确定数据对象占用的内存空间大小
- 确定数据对象的数值范围
- 规定数据对象所能进行的操作(行为)
EXAMPLE:基本整型数据对象占用 4 Bytes(32 Bits) 的内存空间, 数值范围是 0x0~0xFFFF FFFF,可以进行求余运算。
NOTE:需要注意的是,类型数据对象所占用的内存空间和数值范围,除了取决于 C 语言本身的常规定义之外,还可能会受到编译器的影响。
C 语言 4 大数据类型:
- 基本数据类型
- 派生数据类型
- 指针类型
- 空类型
常量与变量
C/C++ 中,数据具有 “常量/变量” 两种表现形式。首先来看,何为常量?何为变量?
常量:指的是在程序运行过程中其数据值不可更改的量。e.g.
- 整型常量:即整数
- 浮点型常量:又称为实型常量,即小数,可使用小数或指数形式来表示
- 字符型常量:即符号,用单引号括起来的一个字符,具有一般字符和转义字符两种类型
- 字符串常量:即用双引号括起来的多个字符组成的字符序列
- 符号常量:即对常量进行命名,所以字符常量即是常量名,使用 const 或 #define 来定义
变量:表示一个具有名字的,具有特定属性的存储空间。在程序运行过程中该存储空间内的数据值可以被改变。变量具有下列三个要素:
- 变量名
- 数据类型
- 数据值
基本数据类型
基本数据类型清单,如下图:
EXAMPLE: 创建一个基本整型变量
// 声明定义并初始化一个「有符号」基本整型变量 aInt ,初始化为 1
int aInt = 1;// 声明定义并初始化一个「无符号」基本整型变量 uaInt ,初始化为 1
unsigned int uaInt = 1;
无符号数据类型与有符号数据类型的区别:
- 占用相同的内存空间,但表示数值范围不同
- 有符号和无符号仅可用于修饰整型或字符型数据对象
EXAMPLE:若 unsigned char 和 signed char 都占用 1 Byte 的内存空间。signed char 的数值范围为 -128~127,而 unsigned char 的数据范围为 0~255。这是因为有符号数据类型数据的最高位被用作为符号位,而无符号的数据类型数据最高位被用作为数据位。
派生数据类型
数组
定义:具有相同数据类型,并且按照一定顺序排列的一组变量的集合。
特征:
- 有序性:数组元素之间具有固定的先后顺序
- 可索引:通过数组名和下标可以唯一地确定数组中的元素
创建一维数组的语法格式:
// 其中 [] 为下标运算符
数据类型 数组名[常量表达式]
EXAMPLE:
// 例:创建 1 维数组:
int aArray[5] = {1, 2, 3, 4, 5};
NOTE:
- [常量表达式] 不可为变量,C/C++ 不允许对数组的长度做动态定义
- 的作用:
- 数组名除了作为数组辨识名称(display_name)之外,也表示了该数组存储空间的首地址,即数组名本身就是数组的内存入口地址
- 一次只能使用数组中的单个元素,而不能一次使用整个数组
// 正确用法:一次只能使用数组中的单个元素。
// 将 aArray 的数据复制到 bArray 中。
int aArray[5] = {1, 2, 3, 4, 5};
int bArray[5] = {0};
for(int i = 0; i < 5; i++)
{bArray[i] = aArray[i];
}// 错误用法:
int aArray[5] = {1, 2, 3, 4, 5};
int bArray[5] = {0};
bArray = aArray; //不可给整个数组赋值
NOTE:需要注意的是,使用数组时,需要主动的对数组变量进行边界检查。C/C++ 在编译时并没有缺省的边界检查动作,所以在程序运行过程,当数组下标索引值越界时,并不会立即触发错误,存在潜在的逻辑异常风险。
// 如下例所示,aArray[i*j] 在程序进行过程中,下标会超出其数组大小。
// 但是在编译和运行过程中,并不会报错,因此必须由编程人员对此边界进行处理!
int main(void)
{int i, j;int aArray[5] = {1, 2, 3, 4, 5};for (i = 0; i < 5; i++){for (j = 0; j < 5; j++){aArray[i * 5 + j] = i * 5 + j;printf("aArray[%d]=%d\r\n", i * 5 + j, aArray[i * 5 + j]);}}return 0;
}// 上错误示例可改为:
// 当然像示例中的简单数组越界在编程过程中是十分容易避免的,但对于复杂度高的问题,必须是要增加边界检查的。
int main(void)
{int i, j, idx;int aArray[5] = {1, 2, 3, 4, 5};for (i = 0; i < 5; i++){for (j = 0; j < 5; j++){idx = i * 5 + j;if (idx > sizeof(aArray) / sizeof(int)){printf("Err: idx over range!\r\nMax idx = %d,idx=%d\r\n", sizeof(aArray) / sizeof(int), idx);return 0;}aArray[idx ] = idx ;printf("aArray[%d]=%d\r\n", idx , aArray[idx]);}}return 0;
}
结构体
定义:由一系列具有相同或不同数据类型的变量构成的集合。
自定义结构体数据类型语法格式:
// struct 关键字用于定义结构体数据类型
struct 结构体名称
{数据类型 成员名1;数据类型 成员名2;...数据类型 成员名N;
};
EXAMPLE:
// 定义一个 student 结构体类型
// 此时只是声明定义了一个结构体类型,并非实际创建了一个结构体类型变量
struct student
{int num;char name[20];float score;
}
创建结构体类型变量的 3 种方式:
- 直接创建:在声明定义结构体类型的同时创建结构体变量
// 例:在定义了 student 结构体类型的同时,
// 也创建了 zhao, wang, li 三个 student 型的结构体变量。
struct student
{int num;char name[20];float score;
}zhao, wang, li;
- 间接创建:先声明定义结构体类型,再另外创建结构体变量
// 声明定义
struct student
{int num;char name[20];float score;
};// C++ 中,struct 关键字可省略,而 C 中,struct 关键字不可省略
struct student zhao, wang, li;
- 无名创建:当使用直接创建方式时,可以省略结构体类型名,所以称为无名创建
// 注意,由于省略了结构体类型名,因而以后不能再用该结构类型创建其他不同的变量
struct
{int num;char name[20];float score;
}zhao, wang, li;
访问结构体成员:
// 句点符号 "." 作为成员运算符,用于访问一个结构体变量中的某个成员
// 结构体变量名.成员名
zhang.name
联合体
定义:联合体,又称为共用体,可使用几个不同类型的变量共同使用同一段内存空间。
自定义联合体类型的格式:
union 联合体类型名
{数据类型 成员名1;数据类型 成员名2;...数据类型 成员名n;
};
EXAMPLE:
// 创建联合体类型 SizeUnion
union SizeUnion
{char a8;int b32;long int c64;
};
创建 SizeUnion 联合体变量 TransDatas:
SizeUnion TransDatas;
访问联合体的变量成员的语法格式:
联合体成员.成员名 // 联合体变量
联合体成员->成员名 // 指向联合体类型的指针变量
EXAMPLE:声明定义联合体类型 SizeUnion ,创建联合体类型 SizeUnion 的变量 TransDatas,然后对 TransDatas 联合体的成员进行赋值
union SizeUnion
{char a8;short int b16;int c32;
};SizeUnion TransDatas;int main(void)
{TransDatas.c32 = 0x90987654;printf("Part1: Set TransDatas.c32 = 0x90987654\r\n");printf("TransDatas.c32 = 0x%x\r\n", TransDatas.c32);printf("TransDatas.b16 = 0x%x\r\n", TransDatas.b16);printf("TransDatas.a8 = 0x%x\r\n\r\n", TransDatas.a8);TransDatas.b16 = 0x1111;printf("Part2: Set TransDatas.b16 = 0x1111\r\n");printf("TransDatas.c32 = 0x%x\r\n", TransDatas.c32);printf("TransDatas.b16 = 0x%x\r\n", TransDatas.b16);printf("TransDatas.a8 = 0x%x\r\n\r\n", TransDatas.a8);TransDatas.a8 = 0x22;printf("Part3: Set TransDatas.a8 = 0x22\r\n");printf("TransDatas.c32 = 0x%x\r\n", TransDatas.c32);printf("TransDatas.b16 = 0x%x\r\n", TransDatas.b16);printf("TransDatas.a8 = 0x%x\r\n\r\n", TransDatas.a8);return 0;
}
输出结果:
NOTE:
- 联合体变量包含的成员都占用同一块内存空间。各成员使用同一个起始地址。但在某个瞬间,只能有一个成员生效,即内存空间同一时间只会存放一个成员的数据值。
- 联合体变量中的一个成员被赋值后,原有变量成员的数据就会被冲掉。若连续为各个成员进行赋值,那么只有最后一个被赋值的成员的数据值有效。
- 联合体变量不能作为函数参数,函数也不能返回联合体类型,但指向联合体变量的指针变量可以作为函数参数,函数也可以返回联合体类型指针变量。
枚举类型
定义:一个整型常量的集合,列举出可被访问的值的范围,所谓 “枚举” 就是把可能出现的值一一列举出来。
自定义枚举类型语法格式:
// enum 关键字用于定义枚举类型
enum 枚举类型名
{枚举元素1[=整型常量1],枚举元素2[=整型常量2],...枚举元素n[=整型常量n]
};
创建枚举类型变量的语法格式:
enum 枚举类型名 枚举变量名;
EXAMPLE:
// 创建枚举类型 Statusenum
enum Statusenum
{A_Status = 1,B_Status = 2,C_Status,D_Status,E_Status,
};int main(void)
{Statusenum Status; // 创建枚举类型变量 StatusStatus = A_Status;printf("Status = %d, A_Status = %d\r\n", Status, A_Status);Status = B_Status;printf("Status = %d, B_Status = %d\r\n", Status, B_Status);Status = C_Status;printf("Status = %d, C_Status = %d\r\n", Status, C_Status);Status = D_Status;printf("Status = %d, D_Status = %d\r\n", Status, D_Status);Status = E_Status;printf("Status = %d, E_Status = %d\r\n", Status, E_Status);return 0;
}
输出结果:
NOTE:
- 枚举类型定义中的每个枚举元素代表一个整型数值。若自定义枚举类型的同时无赋值行为,则由编译系统会按照定义的顺序为其分配 0, 1, 2, … 的数据值;反之,则以赋予的数值为准
- 枚举元素必须为常量,在枚举定义之外,均不能对枚举元素进行赋值操作
- 各枚举元素不能重名,枚举元素名也不能为程序中其他关键字或变量名
指针类型
定义:
- 指针:一个变量的地址
- 指针变量:一个存放其他变量地址的变量
创建一个指针变量的语法格式:
// 指针变量的定义
数据类型 *指针变量名;
EXAMPLE:
char *p;
// 星号 "*" 表示,其后面的名字是一个指针变量名。即:p 为指针变量名。
// char 表示,该指针变量 p 的数据类型为字符型。
引入了指针之后,C/C++ 中就有了两种访问变量数据值的方式:
- 通过变量名来直接访问
- 通过内存地址块的指针来间接访问
指针运算相关的运算符有以下两种:
- 取地址运算符 “&”:获取变量所占用的存储空间的地址,为单目运算符(只有一个操作数)。
- 取值运算符 “*”:也称指针运算符,获取指针变量所指向的存储空间内的数据值。取值运算符的操作数只能是一个指针变量。
EXAMPLE 1::
// 创建整型指针变量 p
int *p;// 创建整型变量 a,并初始化数据只为 2
int a = 2; // 假定变量 a 的存储地址为 0x8000//获取整型变量 a 的存储地址,并将该地址赋值给指针变量 p。
p = &a; // 结果为:指针变量 p 存储了变量 a 的地址,即 0x8000。
// 之后就可以根据需要,通过 *p 的形式来间接访问变量 a 的数据值 2 了
EXAMPLE 2:
int main(void)
{// 创建 int 类型的变量 a , 并对其进行初始化赋值为 2; int a = 2; // 创建 int 类型的指针变量 p ,并将其初始化,指向变量 a 的内存地址int *p = &a; // 输出变量 a 的地址printf("a's Address = 0x%x.\r\n", &a); // 输出变量 a 的值printf("a = 0x%x.\r\n", a); // 输出指针变量 p 的地址printf("p's Address = 0x%x\r\n", &p); // 输出指针变量 p 的值printf("p = 0x%x\r\n", p); // 输出指针变量 p 所指向的内存单元的值printf("*p = 0x%x\r\n", *p); // 输出指针变量 p 指向的内存单元数据的存放地址,即变量 a 的地址printf("&(*p) = 0x%x\r\n", &(*p)); // 输出变量 a 的内存地址指向的数据值,即变量 a 的值printf("*(&a) = 0x%x\r\n", *(&a));return 0;
}// p,表示指针变量,指向存储空间的地址
// *p,指针变量 p 所指向的存储空间的数据值
// &p,指针变量 p 所占用的存储空间的地址
输出结果:
NOTE:通过上述例子,可见取值运算和取地址运算互为逆运算。
空类型
定义:表示一种未知的类型,不能表示一个真实的变量。
作用:
- 限定函数返回的数据类型
- 限定函数参数的数据类型
EXAMPLE:
void n; // 错误,不能表示真实的变量。
void nFunction(void); // 正确。
void xFunction(char n); // 正确。
空类型指针(void *):表示未知类型的指针,可以指向任意类型变量。
【C 语言入门】数据类型相关推荐
- c语言入门数据类型详解,C语言的基本数据类型入门教程
数据类型包括各种数据类型了我们今天给各位介绍的是我们常用的基本数据类型了,下面一起来看这篇C语言的基本数据类型入门教程吧,具体的如下文介绍. 1.声明头文件,相当于java的导包. //只有函数的声明 ...
- 明解C语言入门篇_第7章_基本数据类型
前言 本文为业余学习<明解C语言入门篇>的记录,包含代码清单和练习题. 开始学习时间:2022年8月21日 +++++++++++++++++++++++++++++++ 第1章 初识C语 ...
- R语言|数据类型————R语言入门到入土系列(一)
本系列将从R语言的基本入门到R语言实战系列,逐步编写R语言的教程. R语言数据类型 R语言的赋值与输出 R语言的数据类型 数据类型的查看 数据类型的转换 R语言的赋值与输出 R语言赋值语法如下: 赋值 ...
- c语言word类型_C语言零基础入门—数据类型
C语言零基础入门--3.数据类型 这一节的主要任务是 讲解C语言的 数据类型 . 1. 数据类型 1.1 何为数据类型 数据类型,其实在我们生活中经常被使用,但是在编程语言中被重新定义了一下,并且加 ...
- 【C语言入门到精通】04 数据类型
[C语言入门到精通]04 数据类型 If a program manipulates a large amount of data, it does so in a small number of w ...
- C语言入门 —C语言基本数据类型, C语言可以用来干嘛?
C语言可以用来干嘛? Q:上学的时候没有想过C语言可以干嘛,就是应付考试,毕业之后再问C语言能干嘛? 答案:整个计算机界的基石都是C语言搭建的,现在有这么多语言都号称要取代C,可是没有一个能做到,反正 ...
- 写一篇C语言入门第一讲
嗨~大家好~ 我是小白,最近才使用这个博客,我是一个计算机系的学生,我会在这里发一些我给我们班其他同学讲C语言入门的博文,希望大家能共享这些资料,当然了,我也很希望大家给我提出好的意见或建议.(P ...
- C#forUnity快速入门(连载2)-C#语言入门
C# for Unity 编程语言快速入门教程(连载2)---C#语言入门 接上篇内容,我们把更多的C#语言入门级编程习题发布如下,希望能够对C#编程小白提高技能有帮助. 三: 学习循环语句(续) ...
- c++ 结构体赋值_《零基础看得懂的C语言入门教程》—(十二)结构体是这么回事
一.学习目标 了解C语言的结构体的使用方法 了解C语言结构体的结构的赋值 了解多种C语言结构体变量的赋值方法和取值方法 目录 <零基础看得懂的C语言入门教程>--(二)简单带你了解流程 & ...
最新文章
- Linux磁盘阵列技术详解(二)--raid 1创建
- Autoit 在word中绘图
- 华为擎云w510_鸿蒙系统之后,华为突然官宣新生态,正式对windows说不
- 如何编写第三方接口_Python接口测试之数据驱动
- struts2 s:optiontransferselect 标签的使用
- 【数据结构与算法】之深入解析“砌墙”的求解思路与算法示例
- jq中查找上级_必备实用技能:在EXCEL中制作下拉菜单
- C语言指针定义变量方式
- 10玩rust_C++工程师的Rust迁移之路(5)- 继承与组合 - 下
- html课做一个网页,菜鸟自学建站 HTML 第三课 制作我的第一个网页_html/css_WEB-ITnose...
- 服务器 重启windows_安装Windows 计算机意外
- 中国天然玉米黄质市场趋势报告、技术动态创新及市场预测
- 自己写的免费的音乐播放器:可以播放txt格式的音乐
- PHP实现图片转字符画
- Letv电视品牌升级为乐融,携手漫威打造超级营销
- windows自带录屏_电脑录屏有哪些快捷键?设置帮助电脑快速录屏
- 金茂服务香港上市破发:大跌29% 公司市值52亿港元
- 机器视觉_HALCON_快速向导_2.用HALCON开发程序
- GPIO输入输出各种模式(推挽、开漏、准双向端口)详解【转】
- 互联网人生存指南 | 每日趣闻
热门文章
- 学生信息管理系统 C语言程序设计
- SAP HANA 新增一列时报错详解
- (1)stata的基本使用--数据导入与处理
- 【路径规划】OSQP曲线平滑 公式及代码
- 获取BarTender10.1和新建一个BarTender模板
- 使用前端后台管理模板库admin-lte
- 【总结整理】租房产品创业的三个方向和三个产品---摘自《人人都是产品经理》...
- English trip V1 - 21. I dreamed dream Teacher:Corrine Key: past tense(过去式)
- OpenGLSL初探(六)使用GLSL实现滤镜之灰度滤镜、正方形马赛克滤镜、六边形马赛克滤镜和三角形马赛克滤镜
- 开源脚手架项目大推荐