前言:
变量和数据类型都是与我们生活息息相关的,那么如果想更加了解C语言,学习变量和数据类型是不可缺的,那么这一章节,就让我们来认识认识,什么是变量?什么是数据类型?
一.变量(Variable)
#1.什么是变量?
变量是来源于数学,在计算机中是能存储计算结果或者能够表示值的一个抽象概念 。 变量是能够让你把程序中准备使用的每一段数据能够赋值给一个简短,利于记忆的名字,数据可以通过变量进行访问。如:10我可以赋值给a,a = 10,那么我可以通过a来访问到10 ,所以变量是非常有用!
#2.变量的命名规则
1.
我们需要给变量取一个合适的名字,就像生活中,每一个人都有属于自己的名字,在C语言中也一样,能够有效的进行区分。
#1.变量名必须以字母或者下划线(" _ ")开头,名字中间只能由字母,数字和下划线组成。
#2.变量名的长度不能超过255个字符,也没必要取那么长的名字。
#3.变量名是不能与关键字(保留字)同名 , 关键字都有int / long /auto / 等。
#3.变量的使用
1.
我们已经知道了变量的命名规则,那么如何去使用变量?我们在生活中会找一个小箱子来存放物品,一是显得不凌乱,二是方便找到。计算机也是这个道理,C语言中会在内存中申请一块空间,来进行存放数据。
2.
int是一个英文单词,是Integer的缩写,意为整数,a是我们给这块区域起的名字,当然我们也可以起其它的名字,只有遵守命名规则,你觉得起得有意义即可。
这个语句的意思为:在内存中申请一块区域,命名为a,用它来存放整数。注意的是int 和 a之间是要有至少一个空格,它们是2个词。当然了无论什么语句,都要用分号来结束。那么int a;仅是在内存中找了一块可以保存整数的区域,如何将10,20,99这样的数放入?
我们可以使用 "=" 这个符号,在数学中为"等于号" ,例如: 10+20 =30 , 在C语言中,这一过程为赋值(Assign)。赋值是指把一个数据放到内存的过程。
我们可以看到已经成功的把10赋值给了a变量,并且对它进行编译也是没有报错。
3.
我们也可以使用调式观察到10确实是存放在了变量a中。
4.
那么赋值可不可以进行多次赋值 ?
其实是可以的,我们第一次赋值的值为10,随后第二次赋值把a中的10改为了20,最后一次赋值就把20改为了30,最后打印出的值就是为30。
5.
那么我们也可以使用调式,来观察看看是如何进行多次赋值更改a中的值。我们可以看到视频中的随着右边小箭头不断向下,左边a中的值是不断的变换。经过多次的赋值,最终a的值就为30。
6.
也正是因为a的值是可以改变,所以我们也起了个特别形象的名字为,变量(Variable)。int a;创造了一个变量a,我们把这个过程叫做变量的定义。a = 10;把10给了a,我们叫做赋值。因为是第一次的赋值,也叫做变量的初始化,或者赋初值。
二.数据类型(Data Type)
1.
我们在介绍变量中也提到了数据类型,int就是数据类型,是为整型类型。那么数据类型都有哪些?该如何去使用?接下来我们就介绍数据类型。
C语言是提供了丰富的数据类型来描述我们生活中的各种数据。使用整型类型来描述整型,使用浮点类型来描述小数,使用字符类型来描述字符。那么为什么会有这些类型的存在?是因为只有规定了这些类型,编译器才知道怎么操作数据,这次我们就说明内置类型。
#1.字符型
1.
char其实就是character的缩写,意为字符。那么在C语言中一个字符如果要赋值给一个变量就需要用(char字符型),来表示这个变量存储了一个常量为字符型。
char //character字符
[signed] char //有符号的字符
unsigned char //无符号的字符
2.
那么如何去使用?
如果我们要把一个字符如:'a' , 'b' ,'c' 等等,赋值给一个变量那么这个变量的数据类型为char字符类型,需要注意的是如果是字符需要用英文单引号(' ') ,是字符串需要用英文双引号(" ")。来进行区分的表示,当我们暂时不知道赋值给变量什么时,可以赋值0,作为变量的初始化。
当我们需要进行打印的时候,是字符我们可以用(%c)占位符来进行打印,是字符串可以用(%s)来进行打印。
3.
那么我们也可以通过调试来进行观察数据在变量中的存储。我们可以看到这些字符的存储都是以ASCll码,在图中小写 ' w ' 的ASCll码为119,大写 ' W ' 为87 ,字符串"abcd" 为字符数组,也是以ASCll码来进行存储的。这些ASCll码值最后会转为二进制进行存储,所以我们也得知字符在内存中存储是以二进制的形式进行存储。
#2.整型
1.
当一个整型的常量赋值给一个变量,那么变量就需要用(int整型)来表示这个变量存储的值为整型常量。
对于整型它的类型就有4种,分为短整型,整型,长整型,长长整型。那么单从名字就可以看出它们的存储大小和数据范围是不一样的,短整型能存储的数据范围短一些,长长整型就相对更长,能存放的数据范围更长。
short [int] // 短整型
[signed] short [int] // 有符号的短整型
unsigned short [int] // 无符号的短整型
int // 整型
[signed] int // 有符号的整型
unsigned int // 无符号的整型
long [int] // 长整型
[signed] long [int] // 有符号的长整型
unsigned long [int] // 无符号的长整型
C99中引入的更长整型(长长整型)
long long [int] // 长长整型
[signed] long long [int] // 有符号的长长整型
unsigned long long [int] // 无符号的长长整型
2.
那么如何去使用?
当我们存入的数据为较小的值,取值范围没有那么长我们可以使用short短整型,当然也可以使用其他的整型类型。
但是如果一个数能使用short短整型就能进行存储的话,其实就没有必要使用其他的整型类型,因为会造成一个空间的浪费。
其实就相当于我需要装一个杯子的水,那么使用杯子就行了,没有必要去使用一个大桶,从而造成一个空间的浪费,那么我们知道了不同整型类型能够存储的取值范围是不一样的,我们以后创建变量,存储的值也可以按照情况,来选择对应的整型类型,如:一个人的年龄,那么我们可以用short短整型就够了,更长的值可以用int 或者 long 再或者 long long 。
short int 我们也可以写成 short 相对的,其他整型类型也一样。
当我们不知道给(int整型)类型的变量赋值什么时,可以赋值一个0,作为变量的初始化。
3.
当一个数太大了,我们就需要用对应的整型类型,来表示变量的类型,如图中红色圈的部分,我给了一个很大的数字,但是我用(short短整型)来表示 b 变量的类型,可以看出打印出来的是错误的数字,是因为(short短整型)不能表示太大的数字,放不下。
当我把类型换成(long long )长长整型,当打印时,可以看到打印的数字是正确的。是因为(long long)长长整型,就是用来表示我能够存放的数字更大,取值范围更长。
所以当我们赋值给变量一个值时,也要选择对应的整型类型,取值范围短些,可以用(short 短整型或 int 整型),取值范围长些可以用(long 长整型 或者 long long 长长整型)。
4.
值得注意的是在打印short a和int b时我们可以使用(%d)来进行打印,但是打印long c 我们需要用 (%ld) ,long long d 我们需要用的是(%lld)。
#3.浮点型
1.
浮点类型,顾名思义就是用来存储小数的,如:3.14159 或 9.9 或 0.1 等等。当一个小数赋值给一个变量的时候就需要用到(float浮点型)来表示类型为浮点型。
我们可以看到浮点型类型有3种,分别为(float单精度),(double双精度)以及(long double更大的双精度)。它们都是用来表示小数的,区别只不过是能表示的精度范围不同。如:(float单精度)和(double双精度)相比,那么(double双精度)能表示小数点后的位数更多。那么一样的(long double)能表示小数点后的位数也比(double 双精度)更多。
float // 单精度浮点数
double // 双精度浮点数
long double // 更大的双精度浮点数
2.
如何进行验证?
通过下图,可以看到我把一个精度特别高的值赋值给了a变量。观察到左边红色圈,我通过编译,结果报出了警告。信息为 "double" 到 "float" 发生了截断。这是因为这个值精度太大,然后我们可以看到 a变量的浮点数类型为(float 单精度),(float 单精度)能够表示的精度比较低,这个值精度太高,所以才会报出发生截断信息。那么我们把视线移动到右边绿色圈中,我们可以看到a变量的浮点数类型为(double 双精度), 通过编译生成的解决方案,也是没有报出截断信息的错误。
这就说明了,(double 双精度)的精度范围比(float 单精度)的精度范围更大,一样的(long double 更大的双精度)能够表示的精度范围就是这3个中最大的。以后根据值的精度范围,我们就可以选择正确的浮点数类型来进行使用。
3.
我们已经了解了浮点数的类型,那么该如何去使用?
如果赋值给变量的值为小数,那么直接用浮点数类型来表示就可以了。当不知道赋什么值时,可以赋值(0.0)作为变量的初始化。如果是使用(float单精度)那么打印时,占位符为(%f) , 如果是(double 双精度)那么打印时,占位符为(%lf),如果是(long double 更大的双精度)那么打印时,占位符使用(%lf)。
4.
值得注意的点是当使用浮点数类型(float 单精度)时,赋给变量的值,编译器会默认为是(double 双精度)。所以当我们使用(float 单精度)作为变量的浮点数类型时,我们可以在值的后边加个小写的(f),这也就不会报出警告。
#4.布尔类型
1.
布尔类型是用来表示判断真假的函数,那么C语言原来是没有为布尔值单独设置一个类型,而是使用整数 0 来表示为假。非 0 值表示为真。布尔类型是在C99中引入的,用来专门判断真假。
_Bool
2.
如何使用布尔类型?
首先布尔类型的使用需要包含对应的头文件
#include<stdbool.h>
布尔类型变量的取值是:true 或者 false 。
代码的演示
当我的flag值为true时,表示为真,那么就打印出 "i like you "
当我的flag值为false时,表示为假,那么就打印出 "i hate you "
3.
布尔类型有2种写法,上面的写法和下面的写法都是表示为布尔类型。
三.各种数据类型的长度
1.
我们已经介绍了多种的数据类型,那么每一种数据类型都有自己的长度,使用不同的数据类型,能够创建出长度不同的变量,变量长度的不同,存储的数据范围也不同。
要想求出数据类型的长度就需要用到(sizeof 操作符)。
#1.sizeof 操作符
1.
sizeof 是一个关键字,也是操作符,专门是用来计算sizeof的操作数的类型长度的,单位为字节。
sizeof 操作符的操作数可以是类型,也可以是变量或者表达式。
sizeof( 类型 )
sizeof 表达式
2.
注意点:
1. sizeof的操作数如果不是类型,而是表达式的时,可以省略掉后边的括号。
2. sizeof的后边的表达式是不参与真实运算的,根据表达式的类型来得出大小。
3. sizeof计算的结果是 size_t 类型的。
3.
那什么是size_t类型的?
是因为sizeof运算符的返回值,C语言规定了是无符号整数,并没有规定具体的类型,而是留给系统自己去决定,sizeof到底返回什么类型。
在不同的系统中,返回值的类型可能是(unsigned int )也有可能是(unsigned long ),或者是(unsigned long long) ,printf()对应的占位符为(%u) , (%lu) ,(%llu)。因为这样不利于程序的可移植性。C语言提供了一个解决方法创造一个size_t,统一用来表示sizeof的返回类型,那么我们printf()对应的占位符就为(%zd)。
4.
求出数据类型长度
这是在vs2022 X64配置下的输出:
我们可以看到为什么 int 和 long 是一样大?其实只要 long >= int 就可以了。
5.
sizeof中表达式是不参与计算的
让我们用代码来验证一下
是因为sizeof在代码进行编译时,就已经根据表达式的类型确定了,而表达式的执行是要在程序运行期间才能执行。在编译期间就已经将sizeof 处理了,所以在运行期间就不会执行表达式。
四. signed和unsigned的区别
#1. signed和unsigned的介绍
在前别的数据类型中,也出现了signed 和 unsigned 。那么什么是signed 和 unsigned ?
在C语言使用 signed 和 unsigned 关键字修饰 字符型 和 整型类型。
signed 关键字,表示一个类型带有正负号,包含负值 。
unsigned 关键字,表示该类型不带有正负号,只能表示零和正整数。
对于int 类型来说,默认是带有正负号的,也就是说 int 同等于 signed int 。既然是默认了,所以关键字 signed一般都省略不写,写了也不会错。
signed int a;
// 等同于int a;
int 类型也可以不带正负号。只能表示非负整数。这时就只能使用关键字unsigned声明变量。
unsigned int a;
#2.代码的举例
让我们用代码更为细致的表达
这一例子我们用有符号signed int 来举例,也就是 int类型 。那么 int 类型声明的变量可以是正整数,也可以是负整数,也可以是零。
这一例子我们用无符号unsigned int来进行举例。
我们可以看到如果是用unsigned int 声明变量。负整数是不能够赋值给变量的。因为unsigned关键字是只能表示零和正整数。
#3.unsigned比signed的优势
整数变量声明为unsigned的好处是,同样长度的内存能够表示的最大整数值,增大了一倍。如,
16位的signed short int 的取值范围是:-32768~32767,最大是32767,而unsigned short int的取值范围是:0~65535 ,最大值增大到了65535。
为什么会有差别 ?
因为数据存储都是要转化为二进制的形式。简单来说是因为有符号signed它的符号位要来表示正负号,而unsigned它的符号位是不带有正负号的。所以就比signed多了一位,那么能表示的取值范围就更大了。
#4.char是有符号还是无符号
字符类型的char可以为signed有符号和unsigned无符号。
C语言规定char类型默认是否带有正负号,是由当前编译器决定的。这就是说,char不等同于signed char,有可能是signed char 或者 unsigned char。不像int,int就是等同于signed int 。
在vs2022中,char是signed char,有符号的char 。
signed char c; // 范围为 -128 到 127
unsigned char c; // 范围为 0 到 255
#5.数据类型的取值范围
上述的数据类型很多,尤其是整型类型就有short , int , long , long long 4种,为什么有这些类型?
其实每一种类型都有自己的取值范围,就是存储数据的最小值和最大值的区间,有了这些丰富的类型,我们可以在适当的场景下去选择适合的类型。如果要在当前系统上看到不同数据类型的极限值:
我们可以在limits.h文件中看到整型类型的取值范围。
在float.h文件中看到浮点型类型的取值范围。
那么下图也可以看到各个数据类型的取值范围
##完结
感谢大家的阅读,希望我的文章能够给大家带来好的帮助! ! !