1.数据类型介绍
C语言中提供了丰富的数据类型来描述生活中的各种数据。
使用整型数据来描述整数,使用字符类型来描述字符,使用浮点型类型来描述小数。
所谓“类型”,就是相似的数据所拥有的共同特征,编译器只有知道了数据的类型,才知道怎么操作数据。
内置类型:C语言本身就具有的。
自定义类型:自己创造的。(后续文章会详细介绍)
1.1字符型
char 英文全称:character
signed char
unsigned char
1.2整型
短整型: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]
注:[]:代表可以省略。目前只需要了解每一种类型的第一个,关于signed和unsigned的区别,下述内容会详细介绍。
1.3浮点型
float —— 单精度浮点型
double —— 双精度浮点型
long double
注:对于单精度和双精度的区别,后续文章会详细介绍。
1.4布尔类型(_Bool)
C语言原来并没有为布尔值单独设置一个类型,而是使用整数0表示假,非零值表示真。
目前在C99中也引入了布尔类型,是专门表示真假的。
布尔类型的使用需要包含头文件<stdbool.h>
布尔类型变量的取值是:true 或者 false
上图为头文件中已经帮你写好的宏定义(后续文章会详细说明)
1.5各种数据类型的长度
每一种数据类型都有自己的长度,使用不同的数据类型,能够创建出长度不同的变量,变量长度的不同,存储的数据范围就有所差异。
1.5.1 sizeof操作符
sizeof 是一个关键字,也是操作符,专门是用来计算sizeof的操作符数的类型长度的,单位是字节。
sizeof 操作符的操作数可以是类型,也可以是变量或者表达式。
右侧为输出终端(分别为1 2 4 4 8 4 8 8)(不同的编译器可能有些区别,问题不大)。单位:字节。
sizeof 的操作数如果不是类型,是表达式的时候,可以省略掉后边的括号的。
sizeof 后边的表达式是不真实参与运算的,根据表达式的类型来得出大小。
sizeof 的计算结果是size_t类型的。(所以用的是%zd)
注:sizeof 运算符的返回值,C语言只规定是无符号整数,并没有规定具体的类型,而是留给系统自己去决定,sizeof 到底返回什么类型。不同的系统中,返回值的类型有可能是 unsigned int ,也有可能是unsigned long ,甚至是 unsigned long long , 对应的printf() 占位符分别是 %u ,%lu ,&llu,这样不利于程序的可移植性。
因此,C语言提供了一个解决方法,创造了一个类型别名 size_t ,用来统一表示 sizeof的返回值类型,对应当前系统的 sizeof 的返回值类型,可能是unsigned int,也可能是unsigned long long。
sizeof 表达式,这个东西只会计算这个表达式最终的类型。并且这个表达式的计算过程对后续程序的运行无影响。
2.signed 和 unsigned
C语言使用 signed 和 unsigned 关键字修饰字符型和整型类型的。
signed 关键字,表示一个类型带有正负号,包含负值;
unsigned 关键字,表示该类型不带有正负号,只能表示0和正整数。
(初学者目前可以这样记忆,底层原理可后续了解)
对于int类型,默认是带有正负号的,也就是说int等同于signed int。
由于这是默认情况,关键字signed一般都省略不写,但是写了也不算错。
(char--char到底是有符号还是无符号呢?这个不确定,是取决于编译的视线。大部分的编译器上char 就是signed char,但也有少量编译器 char 表示 unsigned char)
整数变量声明为unsigned的好处是,同样长度的内存能够表示的最大整数值,增大了一倍。
比如,16位的signed short int 的取值范围是:-32768~32767,最大是32767;而unsigned short int的取值范围是:0~65535,最大值增大到了65535。32位的signed int 的取值范围可以参看limits.h中给出的定义。
3.数据类型的取值范围
上述的数据类型很多,尤其是整型类型就有short、int、long、long long四种,为什么呢?
其实每一种数据类型都有自己的取值范围,也就是存储的数值的最大值和最小值的区间,有了丰富的类型,我们就可以在适当的场景下去选择适合的类型。如果要查看当前系统上不同数据类型的极限值:
limits.h文件中说明了整型类型的取值范围。
float.h这个头文件中说明浮点型类型的取值范围。
为了代码的可移植性,需要知道某种整数类型的极限值时,应该尽量使用这些常量。
• SCHAR_MIN,SCHAR_MAX:signed char 的最小值和最大值。
• SHRT_MIN,SHRT_MAX:short 的最小值和最大值。
• INT_MIN,INT_MAX:int 的最小值和最大值。
• LONG_MIN,LONG_MAX:long 的最小值和最大值。
• LLONG_MIN,LLONG_MAX:long long 的最小值和最大值。
• UCHAR_MAX:unsigned char 的最大值。
• USHRT_MAX:unsigned short 的最大值。
• UINT_MAX:unsigned int 的最大值。
• ULONG_MAX:unsigned long 的最大值。
• ULLONG_MAX:unsigned long long 的最大值。
注:更多详细内容,请查看各类头文件。
4.变量
4.1变量的创建
了解清楚了类型,我们使用类型做什么呢?类型是用来创建变量的。
什么是变量呢?C语言中把经常变化的值称为变量,不变的值称为常量。
变量创建的语法形式是这样的:
例:int age; //整型变量
char ch; //字符变量
double weight; //浮点型变量
变量在创建的时候就给一个值,叫初始化。
int age = 18;
char ch = 'T';
double weight =96.6;
4.2变量的分类
• 全局变量:在大括号外部定义的变量就是全局变量
全局变量的使用范围更广,整个工程中想使用,都是有办法使用的。
• 局部变量:在大括号内部定义的变量就是局部变量
局部变量的使用范围是比较局限,只能在自己所在的局部范围内使用的。
如果局部和全局变量的名字相同呢?
结果是:局部变量优先使用。
全局变量和局部变量在内存中存储在哪里呢?
一般我们在学习C/C++语言的时候,我们会关注内存中的三个区域:栈区、堆区、静态区。
1.局部变量是放在内存的栈区
2.全局变量是放在内存的静态区
3.堆区是用来动态内存管理的(后续文章会详细说明)
注:其实内存区域的划分会更加详细,后续文章会详细说明。
5.算术操作符:+、-、*、/、%
在写代码时候,一定会涉及到计算。
C语言中为了方便运算,提供了一系列操作符,其中有一组操作符叫:算术操作符。分别是:+ - * / %,这些操作符都是双目操作符。
注:操作符也被叫做:运算符,是不同的翻译,意思是一样的。
使用方法请自学。
6.赋值操作符:=和复合赋值
在变量创建的时候给一个初始值叫做初始化,在变量创建好后,再给一个值,这叫赋值。
赋值操作符 = 是一个随时可以给变量赋值的操作符
6.1连续赋值
赋值操作符也可以连续赋值,如:
C语言虽然支持这种连续赋值,但是写出的代码不容易理解,建议还是拆开来写,这样方便观察代码的执行细节。
6.2复合赋值符
a = a+10; 可以写成 a+=10;
a = a-3; 可以写成 a-=3;
其他类似。
7.单目操作符:++、--、+、-
前面介绍的操作符都是双目操作符,有两个操作数的。C语言中还有一些操作符只有一个操作数,被称为单目操作符。++、--、+(正)、-(负)就是单目操作符的。
7.1 ++ 和 --
++是一种自增的操作符,又分为前置++和后置++,--是一种自减的操作符,分为前置--和后置--。
7.1.1前置++
口诀:先+1,后使用。
例:
a原来是10,到第二行时,a先+1,然后a就变成了11,然后再赋值给b。此时b就是11。
7.1.2后置++
口诀:先使用,后+1。
a原来是10,到了第二行时,a先使用,赋值给b,此时b变成了10,。如果存在第三行,那么从第三行开始,之后的a的值都是11。
(--操作道理相同)
(这一块知识希望同学们不要想复杂了,多动手写几个例子操作一下。)
8.强制类型转换
强制类型转换是万不得已的时候才使用,一般不推荐。
9.scanf 和 printf 介绍
9.1printf
9.1.1基本用法
printf()的作用是将参数文本输出到屏幕,它名字里面的f代表format(格式化),表示可以定制输出文本的格式。(相关代码自己肯定见过,如果没有,请自学或查看第一篇C语言基础概念博客)
printf()不会在行尾自动添加换行符,运行结束后,光标就停留在输出结束的地方,不会自动换行。
为了让光标移动到下一行,可以在输出内容后添加\n。这玩意就是换行符,其实在C鱼眼基础概念有更多转义字符的介绍。
9.1.2占位符举例
本质就是“替换”。例:printf("HELLO %d WORLD",7); 那么输出就是HELLO 7 WORLD。
占位符的第一个字符永远是%。但是后面的d不是绝对的,要根据数据类型进行调整。
那么一个文本里面是否可以有多个占位符?
可以。例:printf("%s is %d years old.","LLL",7);
各位看到区别了吗?一句话概括:一一对应关系。(几个占位符,后面就几个参数)
9.1.3占位符列举
%a:十六进制计数法的浮点数,字母输出为小写。
%A:十六进制计数法的浮点数,字母输出为大写。
%c:字符。
%d:十进制整数。// int
%e:使用科学计数法的浮点数,指数部分的e为小写。
%E:使用科学计数法的浮点数,指数部分的E尾大写。
%i:整数,基本等同于%d。
%f:小数(包含 float 类型和 double 类型)。// float %f double %lf
%g:6个有效数字的浮点数。整数部分一旦超过6位,就会自动转为科学计数法,指数部分的e为小写。
%G:等同于 %g,唯一的区别是指数部分的E为大写。
%hd:十进制 short int 类型。
%ho:八进制short int 类型。
%hx:十六进制short int 类型。
%hu:unsigned short int 类型。
%ld:十进制 long int 类型。
%lo:八进制 long int 类型。
%lx:十六进制 long int 类型。
%lu:unsigned long int 类型。
%lld:十进制 long long int 类型。
%llo:八进制 long long int 类型。
%llx:十六进制 long long int 类型。
%llu:unsigned long long int 类型。
%le:科学计数法表示的 long double 类型浮点数
%lf:long double 类型浮点数。
%n:已输出的字符串数量。该占位符本身不输出,只将值
%o:八进制整数。
%p:指针(用来打印地址)。
%s:字符串。
%u:无符号整数(unsigned int)。
%x:十六进制整数。
%zd:size_t 类型。
%%:输出一个百分号。
注:目前只需要记住加粗的内容就好了。
9.1.4输出格式printf()
printf()可以定制占位符的输出格式
9.1.4.1 限定宽度
printf()允许限定占位符的最小宽度。
上面举例中,%5d表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面就会添加空格。输出的值默认是右对齐,即输出内容前面会有空格;如果希望改成左对齐,在输出内容后面添加空格,可以在占位符的%的后面插入一个 - 号。
注:这个%5d只是表示最少长度为5,当输出内容有6位时,就正常输出就OK了。
%lf 在打印的时候,小数点后默认是打印6位。
9.1.4.2 总是显示正负号
默认情况下,printf()不对正数显示 + 号,只对负数显示 - 号。如果想让正数也输出 + 号,可以在占位符的%后面加一个 + 。
上面举例中,%+d 可以确保输出的数值,总是带有正负号。
9.1.4.3 限定小数位数
输出小数时,有时希望限定小数的位数。举例来说,希望小数点后面只保留两位,占位符可以写成%.2f。
与上面的知识相结合,显而易见,%12.2f表示这个数字显示12位,但是小数点后面就1位。
扩展:上例的12和2可以用*替代的。
printf("%12.2lf",123.45); 和 printf("%*.*lf",12,2,123.45); 等价
9.1.4.4 输出部分字符串
%s 占位符用来输出字符串,默认是全部输出。如果只想输出开头部分,可以用%.[m]s 指定输出的长度,其中[m]代表一个数字,表示所要输出的长度。
例:printf("%.5s","helloworld"); 的输出结果:hellow
9.2 scanf (基础自学,主要补充细节的知识)
当我们有了变量,我们需要给变量输入值就可以使用scanf函数,如果需要将变量的值输出在屏幕上的时候可以使用printf函数。(请自学,无什么门槛)
sacnf 中,占位符后面的那个参数需要的是地址。所以要用 取地址符号&。
9.2.1 基本用法
scanf()函数用于读取用户的键盘输入。
程序运行到这个语句时,会停下来,等待用户从键盘输入。
用户输入数据,按下回车键后,scanf()就会处理用户的输入,将其存入变量。
它的原型定义在头文件stdio.h。
scanf()的语法跟printf()类似。
它的第一个参数就是一个格式字符串,里面会放置占位符(与printf()的占位符基本一致),告诉编译器如何解读用户的输入,需要提取的数据是什么类型。
这是因为C语言的数据都是有类型的, scanf()必须提前知道用户输入的数据类型,才能处理数据。
它的其余参数就是存放用户输入的变量,格式字符串里面有多少个占位符,就有多少个变量。
上面示例中,scanf ()的第一个参数%d,表示用户输入的应该是一个整数。%d 就是一个占位符,% 是占位符的标志,d 表示整数。第二个参数&i 表示,将用户从键盘输入的整数存入变量i。
注:变量前面必须加上&运算符(指针变量除外),因为scanf()传递的不是值,而是地址,即将变量i的地址指向用户输入的值。
如果这里的变量是指针变量(比如字符串变量),那就不用加&运算符。
下面是一次将键盘输入读入多个变量的例子。
上面示例中,格式字符串%d,表示用户输入的是整数。一一对应。
scanf()处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等。
所以,用户输入的数据之间,有一个或多个空格不影响scanf()解读数据。另外,用户使用回车键,将输入分成几行,也不影响解读。
scanf()处理用户输入的原理是,用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符为止。
9.2.2 scanf 的返回值(https://www.cplusplus.com在此处可以查一下看看)
scanf() 的返回值是一个整数,表示成功读取的变量个数。
如果没有读取任何项,或者匹配失败,则返回0。
如果在成功读取任何数据之前,发送了读取错误或者遇到读取到文件结尾,则返回常量EOF(-1)。
EOF 是 end of file 文件结束标志。
补:按ctrl + z 表示空输入。
注:在编程中很多地方都能用到这个原理
9.2.3占位符
scanf()常用的占位符如下,与printf()的占位符基本一致。
%c:字符。
%d:整数。
%f:float类型浮点数。
%lf:double类型浮点数。
%Lf:long double类型浮点数。
%s:字符串。
%[]:在方括号中指定一组匹配的字符(比如%[0-9]),遇到不在集合之中的字符,匹配将会停止,上面所有占位符之中,除了%c以外,都会自动忽略起首的空白字符。%c不忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格。
如果要强制跳过字符前的空白字符,可以写成scanf(“ %c”,&ch),即%c前加上一个空格,表示跳过零个或多个空白字符。
下面要特别说明一下占位符%s,它其实不能简单地等同于字符串。它的规则是,从当前第一个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。
因为%s不会包含空白字符,所以无法用来读取多个单词,除非多个%s一起使用。这也意味着,scanf()不适合读取可能包含空格的字符串,比如书名或歌曲名。另外,scanf()遇到%s占位符,会在字符串变量末尾存储一个空字符\0。
scanf()将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,存储字符串时,很可能会超过数组的边界,导致预想不到的结果。为了防止这种情况,请使用%s占位符时,应该指定读入字符串的最大长度,即写成%[m]s,其中[m]是一个整数,表示读取字符串的最大长度,后面的字符将被丢弃。
9.2.4 赋值忽略符*
只要把*放在任何占位符的%后面,该占位符就不会返回值,解析后将被丢弃。
可以自学查看详细内容。
注:在创建变量的时候,给变量一个初始值,是一种好的编程习惯,如果不给变量初始化,有的编译器会报错。
作者自述:本文主要针对C语言的一些数据类型概念,对此作一个简单介绍。内容中包含了很多链接以及记忆性总结内容,有查阅需求的同学可以收藏一下哦,便于查找。本文制作不易,求求动动你们发财的小手点个赞和关注,这是对我创造最大的动力。后续我也会跟进内容,尽量一周至少一次,保证内容的质量。如果有想知道的内容或者有建议的地方,欢迎后台私信或者在本文留言哦。感谢各位的支持捏Thanks♪(・ω・)ノ。