C语言—数据类型和变量(printf和scanf原理剖析)

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♪(・ω・)ノ。

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值