C语言从入门到精通 第2讲——数据类型和变量

C语言从入门到精通 第2讲——数据类型和变量

前言

本期的主要内容是对C语言中的数据类型和变量中一些易错点或容易忽视的问题进行阐述,再次强调,不太适合没有任何基础的同学哈。那我们正篇走起~

数据类型介绍

我们详细说说这个布尔类型吧,可能有一部分人没有听过,这是个什么东西呢?

我们知道,在条件判断语句中,0代表‘假’,而非0值代表真。这个布尔类型是在C99之后引入的,专门用来表示真假的。但使用这个布尔类型有个前提,那就是得包含头文件<stdbool.h>。那我们具体如何使用呢?我这里就直接上图了。

看到这里,有人可能会好奇,那这个flag在后续的代码中可以被当作数字1处理吗?答案是可以的。

这个flag居然可以当成数字1处理,甚至还能进行算术运算,请看图:

接下来我们讲讲这个sizeof操作符哈

(1)这个sizeof操作符是做什么的呢?它是计算操作数的类型长度的,单位字节

(2)它的操作数可以是什么呢?可以是类型变量、以及表达式

(3)sizeof后面的这个表达式是不参与真实运算的!什么意思呢?请看下图:

通过上图我们注意到a经历了a=a+b的运算之后,按道理是应该等于12的,但打印a的值后,发现它仍然是10。这就是我们所说的sizeof后面的表达式是不进行计算的!

(4)看上图我们可以注意到有个%zu的东西,这是个啥子?因为sizeof是计算各种类型的长度的,这就导致了这个sizeof的返回值(注意sizeof是有返回值的)可能是int可能是float也可能是double或者别的什么类型,那么难道我们每次打印这个返回值的时候还要看看它到底是什么类型吗?这就很麻烦啊,所以C语言就创造了一个类型别名:size_t,用来统一表示sizeof的返回值类型。它对应的占位符就是%zu啦~

(5)如果sizeof后面的操作数是变量而不是类型的时候,我们是可以省略那个常量的括号的哦,请看下图:

接下来我们简单说下各类型的长度吧,请看下图:

ps:某些类型的长度并不唯一,在不同开发环境中可能有所不一样,大家注意鉴别。

signed和unsigned

生活中啊有些数据是有正负零的区别,比如说资产对吧,要是欠债了那不就是负资产了嘛,还比如说温度。那还有一些数据啊就没有负的,只有正和零,比如说身高体重。

那在C语言中啊我们如何来界定一些数据只能为非负数呢?那就要用到unsigned来声明变量,对应的如果一些数据有正有负也有零,那就可以用signed来声明。这是很好记的嘛,signed在英文中的意思可以理解为符号,那unsigned就是无符号。无符号就没有负号呀,只有正和零,不难理解吧。

那这么做有什么好处吗?

有的有的。对于16位的signed short int来说,它的取值范围是-32768到32767,而对于unsigned short int来说,它的取值范围就变成了0到65535,很明显的是它取正值的范围被扩大了。

变量

关于这一块我想详细讲讲全局变量和局部变量。请先看下图:

上图我们可以看出我是在三处定义了相同的变量名称n,但打印的结果却有所不同。

全局变量是指在大括号外面定义的变量,局部变量是指在大括号内部定义的变量。局部变量的范围是有局限的,只能在自己所在的局部范围内才能使用。

那如果局部变量和全局变量的名字相同,就会出现上图的情况,这就是所谓的局部优先

说到变量的命名,有以下几点要强调:

(1)变量名由数字字母下划线构成。

(2)变量的开头不能数字

(3)变量名不能跟关键字重复

(4)变量名是区分大小写的。

(5)长度不能超过63个字符

扩展一下:全局变量存储在内存中的静态区

局部变量存储在内存中的栈区

算术操作符

算术操作符都是双目操作符。包括+、-、*、/、%

需要详细讲的是/和%

第一个除号/的两端如果都是整数,那么它的结果就是直接去掉小数点后面东西的整数。不管赋给的变量是整数还是小数。如下图1

如果两端有一个或多个是小数,那么它的结果就是小数。除非赋给的值是整型。如下图2、3

这也是很好理解的哈。

第二个是%用于求模(余数)运算。需要注意的是

(1)它的两端必须整数

(2)它是可以用于负数的运算的,但是符号取决于第一个运算数的正负号。如下图:

赋值操作符

赋值操作符有两个,一个是赋值符号,一个是复合赋值。

先讲讲这个赋值‘=’吧,需要注意的是连续赋值的情况。连续赋值在C语言中是允许的吗?答案是允许的哈。见下图:

但这样写出的代码不方便理解,所以大家尽量还是少用。

复合赋值运算符就类似与“+=”、“-=”,见下图:

上面的a+=b就相当于a=a+b。

单目操作符

单目操作符的操作数只需要一个。比如自增++、自减--、自增自减里又有前置自增、后置自增,自减是类似的。

那么什么是前置后置呢?先看下图:

上图的这个b++就是后置自增,可以理解为两个流程:第一步:a=b;第二步:b=b-1。大家理解了吗?自减是类似的。

+、-也是单目操作符,它们分别是正号和负号。运算符+对政府没有影响,写了也不会报错。

接下来聊聊强制类型转换哈。请先看图:

我们把一个小数赋给了一个整型变量a,编译器没有报错,但有个警告(看图中下面),说这样做可能丢失数据,这也很好理解嘛,人家一个小数被强制塞到了整数里,那小数点后部分就直接丢了呗。那为了消除这个警告,我们可以在想要转换类型的数据前面加上(想要转换的类型),如下图:

但是嘞,这只是消除了警告,它的数据还是丢失了部分。俗话说强扭的瓜不甜,如果我们在写代码的过程中能不强制转换,那自然是更好的。

scanf和printf介绍

printf

在printf的使用中,我们有一下几点要注意:

(1)printf的占位符与参数是一一对应的,如果参数的数量少于占位符,那它就可能输出内存中的任意值。如下图:

(2)占位符有很多种,我们主要强调下以下几种:

%d是整数

%s是字符串

%c是字符

%f是小数,包括float和double

%hd是十进制short int类型

%hu是unsigned short int类型

%ld是十进制long int类型

%lu是unsigned long int类型

%llu是unsigned long long int类型

%lf是long double类型

%x是十六进制整数

%u是无符号整数

%p是指针(用来打印地址)

%zu是size_t类型

(3)printf中允许限定占位符的最小宽度,请看图:

观察第一张图,我们在%与d之间加上想要限制的最小宽度后,如果那个参数宽度是小于最小宽度时,它会在参数左边补空格,使空格加上参数的总宽度等于最小宽度。如果我们在最小宽度的前面再加上一个负号,那么这时它就会在参数右边补上空格使总宽度为最小总宽度。

观察第二张图,如果参数的宽度大于最小宽度,那么它打印时没有影响,直接输出参数的所有值

除了可以限制整数,它还可以限制小数宽度,与限制整数同理,只不过占位符中把d换成f。(ps:若%f打印小数,则小数点后默认打印6位。)

(4)总是显示正负号

默认情况下,printf()不对正数显示正号,如果想让正数显示正号则在‘%’后面加个‘+’(注意,它并不是简单的在数字前面加个正号,如果数字是负数,那么即使%后面有个正号那最后打印出来也是负数。‘+’更像是一种格式)请看下图:

通过上图还可以看出在%后面加‘-’没有什么用.

(5)限制小数位数

如果我们想要限制小数点后面的位数,举例来说想要小数点后两位,则占位符应该是“%.2f”,如下图:

还可以和限制宽度一起使用,如下图:

除此之外,最小宽度和小数位数这两个限定值都可以用*替代,通过printf()的参数传入,如下图:

我们还能输出部分字符串,如下图:

scanf

如果我们需要给程序中通过键盘输入数据,那scanf就派上了用场。

在这一块中也有几个点需要注意:

(1)scanf的原理是先把用户的输入放入缓存,然后再根据占位符对缓存进行解读,解读用户输入时,从上一次解读遗留的第一个字符开始,直到读完缓存或者遇到第一个不符合条件的字符为止。所以下图情况就不难理解了:

上图中我需要解释几个地方,第一个是‘e’是什么意思,其实这是科学计数法,0.45e12就意味着0.45乘以10的12次方。

第二个地方是为什么0.45乘以10的12次方会变成上图中的数字呢?因为0.45可能在内存中无法精确的保存,所以它可能会变成0.449999999999乘以10的12次方。

(2)scanf也是有返回值的。那它返回的是什么呢?其实是它成功读取的字符个数。如果没有读取任何项或者是读取失败,则返回0;如果在读取成功任何项之前发生了读取错误或者读取到了文件结尾,则返回常量EOF(-1)。

这经常用于算法竞赛中多次读取数据。比如下图结构:

(3)赋值忽略符。有些初学者经常犯的一个错误就是输入的东西和scanf里的格式不一样,什么意思呢?请看下图:

上图中这个b值打印出来明显不是输入的b值呀?这是因为我们输入数值时习惯性的以空格为间隔,但是代码scanf中我们是以逗号为间隔,所以这就导致其实读入b的是逗号,但是b是整型,读不进去逗号所以就随机打印出了内存值。解决办法要么输入的时候以逗号间隔,要么将scanf里的逗号去掉或者改为空格。

那如果我们想要用户输入日期,但是不强调日期的输入格式,那用户输入的日期格式可能千奇百怪,那有什么办法能解决这个问题呢?

有的有的,C语言中还有个赋值忽略符。将*加在任何占位符的%后面,那么该占位符就不会返回值,而是解析后被扔掉,具体操作方法请看下图:

好啦,第二讲的内容就到这里,如果对你有所帮助,希望能够点个赞支持下博主,不胜感激~我们下讲内容再见!