Summary
0)对于所操作数据的具体类型,一定要十分明确!
1)C语言对数据的分类:整数类型、浮点数类型、字符类型(普通字符型、无回显字符型)。各个类型的根本区别在于,所占用的内存大小不同。
2)类型所占的字节数是由编译器决定的,32位和64位的主要区别在于:指针所占字节数分别为4和8;long所占字节数分别为4和8。
3)区分初始化和赋值的关键点:赋值操作是在创建变量时候进行的,还是在创建变量之后进行的。
4) 当遇到以下2种情况时:
- 当前的值已经溢出了(超过了当前类型所能表示的范围里的数)
- 大类型向小类型转换
对于溢出以后的值:
正值:溢出的值 - 当前类型能表示的个数
= 实际值
负值:溢出的值 + 当前类型能表示的个数
= 实际值
5)sizeof用于获得类型或者变量所占用的内存字节数,sizeof作用于数组名时,可以得到数组占用的内存。
6)C语言中字面量的默认类型:如2为int,0.2为double,'2'为char
1、数据类型与变量
1.1 C语言中的数据类型
初学阶段应掌握的类型:
整形:
- int:占用4个字节(32位(bit)),表示范围:-2147483648~2147483647(-231 ~ 231-1)。
- short:占用2个字节(16位(bit)),表示范围:-32678 ~ 32767。
浮点型:
- float:占用4个字节(32位(bit)),表示范围:-3.4 x 1038 ~ 3.4 x 1038。
- double:占用8个字节(64位(bit)),表示范围:-1.7 x 10-308 ~ 3.4 x 10308。
字符型:
- char:占用1个字节内存(8位(bit)),表示范围:-128~127。字符数据使用单引号括起来。包括普通字符(英文字符类型,如'D','t');无回显字符类型(无回显字符必须以反斜杠'\'开头,是一种打印后在屏幕上看不到的字符,如换行符'\n',制表符'\t',这是一个字符);字符类型实际也是种整型。
各个数据类型的根本区别在于,所表示的内存大小不同。
1.2 C语言中变量的命名规则
- 字母(a-z, A-Z)、数字(0-9)、下划线(_)构成的字符序列
- 第一个字符必须为字符或者下划线(不能为数字)
- 大小写敏感(如name和Name是两个不同的变量名字)
// 小测试:以下哪些命名是合法的?()
A.WORD B.-abc C.2c D._1
E.m_test F.a@b G.c3 H._
// A、D、E、G、H合法
变量命名的规范:
1)见名知义:变量命名一定要一眼能看出这个变量的用途
2)便于阅读:可以遵循一些规范,如“驼峰规范”,方便自己和他人阅读、维护代码。
1.3 C语言中变量的定义
C语言中创建变量的语法:type name;
如下:
int n1;
double n2;
short n3;
初始化:在创建变量的同时,给变量一个值。
赋值:在创建变量之后,改变变量的值。
int n1; // 定义变量,名为n1,类型为int
double hello; // 定义变量,名为hello,类型为double
int n2 = 2; // 定义变量,名为n2,类型为int,并初始化为2
n1 = 1; // 赋值操作,改变n1的值,使其表示1
2、深入数据类型与变量
2.1 程序中数值的类型
C语言是类型严格的语言,字面量也有类型,使用字面量时也需要考虑字面量的类型。字面量的类型包括默认类型和指定类型,如:
- 默认类型:2为int,0.2为double,'c'为char
- 指定类型:0.2f为float(后缀f表示float)
每种类型都有自己的容量(所占内存的大小),如果将大类型的值赛道小类型的容器内,可能放不进,会溢出。
大类型赋值给小类型时,可能发生溢出:
- 当数值在小类型范围内 --> 赋值成功
- 当数值超过小类型的范围 --> 发生溢出
小类型可以安全的赋值给大类型:
- 浮点型赋值给整形,会发生截断 --> 小数部分丢失
- 整形赋值给浮点类型 --> 赋值成功
int a = 50000; // valid:50000是一个字面量,默认类型为int,在int能表示的范围内
short b = 0; // 0是一个字面量,默认类型为int,int到short类型的转换,可能出问题。
// 实际上0在b能表示的范围内,所以能正常赋值
b = a; // oops!赋值操作,改变b的值为int类型的50000,超过了b能表示的范围,坏了
// 输出:b = -15536。为何是该值,见summary
2.2 类型转换
C语言中不同类型的变量之间(变量与字面量之间)进行赋值或运算时,会发生类型转换。类型转换不改变原变量的值,仅仅是被赋值的变量的值发生改变,并且可能会不正常。
开发小知识:
- 开发环境(编译软件)由编辑器和编译器组成
- 编辑器:负责程序的编写工作(字处理软件)
- 编译器:负责程序的编译工作(文本转为二进制)
- C语言编译器检查类型的同时,可能做默认转换
- short s = 2; // 字面量2,类型为int,被转换为short
- double d = 2; // 字面量2,类型为int,被转换为double
默认类型转换:编译器知道字面量2的类型是int,但也明确的知道初始化操作可以成功(因为2在short可以表示的范围内),因此编译器就会悄悄的将2的int转换为short。
强制类型转换:也叫强制类型转换。规则:type name = (type)var;
int i = 40000;
short b = (short)i;
printf("i = %d\n", i); // i = 40000
printf("b = %d\n", b); // b = -25536
以上代码也验证了,类型转换不会改变原来变量的值,只是改变被赋值变量的值,且可能会发生异常(如b期望是40000,但实际输出是-25536,原因见summary4))。
3、再论数据类型
3.1 如果值超过了类型所能表示的最大范围该怎么办
代码见2.2。40000超过了short能表示的范围,这时候表示的值是个奇怪的值。结论如下:
*当遇到以下2种情况时:*
1)当前的值已经溢出了(超过了当前类型所能表示的范围里的数)
2)大类型向小类型转换
对于溢出以后的值:
正值:溢出的值 - 当前类型能表示的个数 = 实际值
负值:溢出的值 - 当前类型能表示的个数 = 实际值
代码分析:
short b = 40000; // output: -25536
// 40000是溢出后的值(正值);short类型占用内存16bit,能表示2^16个数;
// 实际值 = 40000 - 2^16 = 40000 - 65536 == -25536
unsigned short s = 0;
s = s - 1; // output: 65535
// -1是溢出后的值(负值);short类型占用内存16bit,能表示2^16个数;
// 实际值 = -1 + 65536 = 65535
最后:程序运行时如果发生了越界:
- 大于类型最大值,则:运行结果回转到最小值附近
- 小于类型最小值,则:运行结果回转到最大值附近
3.2 sizeof关键字
sizeof用于获取类型或者变量所占用的内存大小(字节)
用法:
sizeof(type)
sizeof(variable)
sizeof variable // 此种方式并不为工程中常用
int var = 1;
printf("%d\n", sizeof(var)); // 4
printf("%d\n", sizeof(int)); // 4
printf("%d\n", sizeof var ); // 4
3.3 补充知识
1)整型的扩展知识:
signed和unsigned可以与char、short、int组合使用
常规写法 | 完整写法 | 表示的数据范围 |
---|---|---|
char | signed char | -128~127 |
unsigned char | unsigned char | 0~255 |
short | signed short | -32768~32767 |
unsigned short | unsigned short | 0~65535 |
int | signed int | -2147483648~2147483647 |
unsigned int | unsigned int | 0~4294967295 |
2)对于打印输出,不同的类型值,要具体对应使用不同的格式化字符。
类型 | 对应的格式化字符 | 占用内存 |
---|---|---|
int | %d | 4 |
unsigned int | %u | 4,(有无符号不影响占用的内存) |
short | %d | 2 |
char | %c, %d | 1 |
long | %ld | 4 / 8, 分别对应32位和64位编译器 |
long long | %lld | 8 |
float | %f | 4 |
double | %f | 8 |
如果使用了不匹配的格式化字符,输出则可能有问题:
// eg.1
unsigned int u = 2147483648;
printf("u = %d\n", u); // -2147483648
printf("u = %u\n", u); // 2147483648
//eg.2
unsigned char c = 128;
printf("c = %d\n", c); // 128
例1中,为什么2147483648在unsigned int表示的范围内,第一次输出还是不对?
原因在于,%d格式化字符是针对有符号整型的,所以此时将u看做一个int,应用summary4)的计算方法,确实输出了-2147483648。如果按照正确的输出方式%u,则输出的是期望值2147483648。
例2中,unsigned char c的值是128,也是以%d的方式进行打印输出,此时128超过了signed char能表示的范围,为什么不像例1中打印出错呢?
原因在于,128这个值太小了,如果小于signed int能表示的最大值(2147483647),以%d方式打印就不会出错;如果大于了2147483647,那么%d打印就会出错了。
所以,数据什么样的类型,就严格用对应的格式化字符去匹配。
3)左值和右值
左值:可以出现在赋值符号左边的值,如:变量
右值:出现在赋值符号右边的值,如:变量、字面量、计算结果(为右值)
4)数据的表示(简略,见后续C进阶课程)
浮点类型(float&double)对数据的表示是不准确的
整数类型(char,short,int,long)对数据的表示是准确的
浮点类型与整数类型在内存中对数据的表示法完全不同
本文总结自“狄泰软件学院”唐佐林老师《C语言入门课程》。
如有错漏之处,恳请指正。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。