2 数据类型和变量

目录

一、数据类型  &  signed 和 unsigned  &  取值范围

(一)数据类型

        1、字符型

        2、整型(整数)

        3、浮点型(小数)

        4、布尔类型(真 or 假)

        5、数据类型所占的内存大小

        (1)sizeof 的使用

        (2)数据类型的大小

(二)signed 和 unsigned

(三)取值范围

二、变量

(一)变量创建 & 初始化 & 赋值

(二)变量的分类

(三)变量的储存

三、算数操作符:  +  -  *  /  %

四、赋值操作符: = & 复合赋值

(一)赋值操作符

(二)复合赋值

五、单目操作符:  ++(自增)  --(自减)  +(正)  -(负)

六、强制类型转换

七、细说 printf & 详讲scanf

(一)细说printf

        1、基本用法

        2、占位符

        3、打印显示正负号

        4、打印限定宽度

        5、打印限定小数位数

        6、输出部分字符串

(二)详讲scanf

        1、基本用法

        2、返回值

        3、scanf()的占位符

        4、赋值忽略符

八、我觉得有意思的点

(一)sizeof 的打印

(二)scanf()的储存原理

(三)scanf()占位符注意事项


一、数据类型  &  signed 和 unsigned  &  取值范围

(一)数据类型

c12d9561e1254400aca06910d673c2b5.png

        内置类型:C语言本身就有

        自定义类型:顾名思义,用户自己定义的

        1、字符型

[]中的内容可省略

char
[signed] char  
unsigned char

        2、整型(整数)

[]中的内容可省略

1 短整型
short [int]
[signed] short [int]
unsigned short [int]

2 整型
int
[signed] int
unsigned int 

3 长整型
long [int]
[signed] long [int]
unsigned long [int]

4 更长的整形
long long [int]
[signed] long long [int]
unsigned long long [int]

        3、浮点型(小数)

float
double
long double

        4、布尔类型(真 or 假)

        使用时要包含头文件 stdbool.h

#include<stdbool.h>

bool  

        5、sizeof 计算数据类型所占的内存大小

        使用 sizeof 来计算【某变量】或【某数据类型】所占的内存,返回的是所占用的内存大小,和【该变量或数据类型中】保存的数值内容没有任何关系。(单位:Byte 字节,1 Byte = 8 bit

        (1)sizeof 的使用

sizeof (类型)
sizeof 表达式

        注:若为表达式,则表达式不真实参与运算

        (2)数据类型的大小

printf("%zd\n",sizeof(类型));

7e3f38b7202145fcb32f26a9cf2a88b8.png

常用类型所占用的内存大小(单位:字节)

表出处:王健伟,《C++新经典》,清华大学出版社,2020年8月出版,表2.1

(二)signed 和 unsigned

         字符型 整型 才被关键字 signed 和 unsigned 修饰

        注:

        ① signed关键字,表示一个类型带有正负号,有负值

        ② unsigned关键字,表示该类型不带正负号,只表示零和正整数;正因为不表示负值,负值的取值范围会加到正值上,因此unsigned声明变量,可使该变量的取值范围增大一倍

9182552e56ea42cb8c1f6c741716f0ce.png

每种数据类型能够取值的范围(可能不全)

表出处:王健伟,《C++新经典》,清华大学出版社,2020年8月出版,表2.2

       

        ③ signed int == int ,unsigned int == unsigned ;

             但 char 可能等同于 signed char ,也可能等同于unsigned char ,取决于编译的实现,大部分编译器上char == singned char

        ④有符号整数使用"%d"打印,无符号使用"%u"(unsigned )打印

(三)取值范围

① 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 的最大值;

二、变量

        变量:其值可以改变的量

(一)变量创建 & 初始化 & 赋值

41222f853bd34e07b6d78aad9b0beafa.png

       出处:王健伟,《C++新经典》,清华大学出版社,2020年8月出版

        

        省略 [ ] 则为创建

        不省略 [ ] 则为初始化

        在创建变量时给一个初始值是一种好的编程习惯,如果不给变量初始化,有的编译器会报错(局部变量不初始化的时候,他的值是随机的;全局变量不初始化,默认值为0)
 

int a;  创建(与定义的格式一样)
char b = 3.14;  初始化
a = 10;  赋值

(二)变量的分类

        全局变量:在大括号外部定义的变量;整个工程都能使用(共享充电宝)

        局部变量:在大括号内部定义的变量;在自己局部范围内使用(自家充电宝)

#include<stdio.h>

int a = 100;  //全局变量
int main()
{
    int a = 10;  //局部变量
    printf("%d\n",a);  
    return 0;
}

        上面代码会输出10,当全局变量名和局部变量名同名时,优先使用局部变量

(三)变量的储存

        学习C语言时,我们会关注内存的三个区:栈区,堆区,静态区

  • 栈区:局部变量、函数参数
  • 堆区:动态内存管理
  • 静态区:全局变量、静态变量

三、算数操作符:  +  -  *  /  %

        操作符(运算符)两边的数称为操作数,以上算数运算符有两个操作数,这种操作符也称双目操作符

        +(加)、-(减)、*(乘)、/(除)、%(取余数)

        /(除)操作符要得到小数结果,至少要一个操作数是小数

4.0 / 1 == 4.0
4 / 1.0 == 4.0

        %(取余数)操作数只能是整数,结果的正负取决于第一个操作数

四、赋值操作符: = & 复合赋值

(一)赋值操作符

        将等号右边的值赋给左边的变量

(二)复合赋值

        【赋值 " = " 】之前加其他运算符,构成复合赋值运算符

int a = 3;
a = a + 2;
a += 2;  复合赋值,效果同上句

五、单目操作符:  ++(自增)  --(自减)  +(正)  -(负)

        ++(自增)分为前置++ 和后置++ ,--(自减)同理;

                前置:先自增(减),后使用

                后置:先使用,后自增(减)

        +(正),-(负):改变一个值的正负号

六、强制类型转换

e5590115406e4d4d9d4ffd091ed18416.png

出处:王健伟,《C++新经典》,清华大学出版社,2020年8月出版

int a = (int)3.14;

double x,y;
x = 5.0
y = 2.0

a = (int)(x/y);

        强扭的瓜不甜,不在万不得已的情况下一般不会使用强制类型转换

七、细说 printf & 详讲scanf

(一)细说printf

        1、基本用法

        把双引号中的内容进行输出,使用前引入头文件 stdio.h

        注:printf()不会自动换行,善用 "\n" 来换行

        2、占位符

        在双引号中的输出内容中“占位置”,会和后面的值进行交换;

        多个占位符,占位符与后面的值要一一对应

        注:占位符的第一个字符一律为百分号%(占位符标志),第二个字符决定输出结果

        常用占位符:

                %c  字符

                %d  十进制 int 类型

                %f  小数(包括 %f -- float 类型 和 %lf --  double 类型) 

                %hd  十进制 short int 类型

                %ld  十进制 long int 类型

                %lu  unsigned long int 类型

                %Lf  long double 类型

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

                %s  字符串

                %u  unsigned int 类型

                %x  十六进制 int 类型

                %zd  size_t 类型

        3、打印显示正负号

printf("%+d",12);  输出:+12
printf("%+d",-12);  输出:-12

        上例 "%+d" 可以保证输出的值,总是带有正负

        4、打印限定宽度

a7194ceb9afa4ef5967d05f5e6524de0.png

        占位符可以限定最小宽度,默认右对齐,希望左对齐则补负号(-)

        小于最小宽度补空格,大于正常输出

        作用:输出对齐

int a = 123;    
printf("%5d",a);  
限定最小为五位数,输出:空格 空格 123

printf("%-5d",a);  
输出:123 空格 空格

        对于小数,%f 和 %lf 打印是默认小数点后面有六位:

double a = 123.45;
printf("%12lf",a);  
输出:空格 空格 123.450000    

        5、打印限定小数位数

6fbefea3ac064b2db2a2d6d99d2d7933.png

        ① 希望限定小数位数则可以使用,超过小数限定位数则会四舍五入(默认有六位小数)

printf("%.2f",3.1);  输出:3.10
printf("%.2f",3.145);  输出:3.15

       

         ② 可与限定宽度混合使用

a4598dd2b7954d7f9cb779505ab5ae0d.png

printf("%6.2f",2.365); 
输出:空格 空格 2.37

        

        ③ 最小宽度 和 小数位数 是可以通过 * 来传参

printf("%*.*f", 6, 2, 32.5);
输出:空格 32.50

        6、输出部分字符串

75fdd2cf243541fcb83fad984d73390c.png

printf("%.5s\n", "hello world");
输出 hello

(二)详讲scanf

        1、基本用法

        用于读取用户的键盘输入

a6dba9d9eb2a488ba279b76da11408a7.png

int a;
scanf("%d",&a);
& 为取地址符

        用户输入数据、按下回车键后,scanf()会处理用户的输入,将其存入变量

        可以传多个值:

scanf("%d %d %f %f", &i, &j, &x, &y);

        输入多个值,为了直观和消除每个值之间的空白字符,每个占位符之间可以用空格隔开;

        不用空格隔开也可以,因为scanf()运行时,会自动过滤空白字符,包括空格、制表符、换行符等,因此一个或多个空格不影响scanf()解读数据,另外,使用回车键,将输入分成几行,也不影响解读

        

        用户输入要严格匹配格式串,如:

scanf("%d,%d", &i, &j);
用户输入:整数,整数

        2、返回值

        若读取成功,则返回读取的个数

        读取失败(读取错误或读取到文件结尾),则返回 EOF(end of file 文件结束标志)

        注:ctrl + z 能提前结束输入

        3、scanf()的占位符

        如下,与printf()的占位符基本一致

        %c  字符

        %d  整数

        %f  float 类型小数

        %lf  double 类型小数

        %Lf  long double 类型小数

        %s  字符串

        %[ ]  在括号中指定匹配的字符(如:%[0-9]),遇到不在集合之中的字符,匹配会停止

        4、赋值忽略符

        有时,用户的输入可能不符合预定的格式

#include <stdio.h>

int main()
{
    int year = 0;
    int month = 0;
    int day = 0;
    scanf("%d-%d-%d", &year, &month, &day);
    printf("%d %d %d\n", year, month, day);

    return 0;
}

        用户不严格按照 【整数 - 整数 - 整数】 的格式输入,可能是 【整数 / 整数 / 整数】

        为了避免这种情况,scanf()提供了一个【赋值忽略符 " * " 】,只要加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃

scanf("%d%*c%d%*c%d", &year, &month, &day)

        用户不论是按照【整数  整数  整数】,【整数 - 整数 - 整数】还是【整数 / 整数 / 整数】 的格式输入,都会忽略掉整数之间的字符,因为解读后被丢弃了

八、我觉得有意思的点

(一)sizeof 的打印

        sizeof 运算符的返回值,C语言只规定是无符号整型,所以可能是 unsigned int 或 unsigned long 或 unsigned long long ,对应的printf占位符是"%u","%lu","%llu",这不利于代码的可移植性,C语言提供了一个解决方法,创造出一个 size_t 类型来统一表示无符号整型的返回值,用"%zd"进行打印。

(二)scanf()的储存原理

        用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读

        解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符为止

        例:

#include <stdio.h>

int main()
{
 int x;
 float y;
 
 // ⽤⼾输⼊ " -13.45e12# 0"
 scanf("%d", &x);
 scanf("%f", &y);
 return 0;
}

        过程:

                "%d" 占位符会忽略起首的空格,从" - " 处开始获取数据,读取到"-13" 停下来,因为后面的" . "不属于整数的有效字符,这就是说占位符"%d"会读到"-13";

                第二次调用 scanf() 时,就会从上一次停止解读的地方,继续往下读取,这一次读取的首字符是"."由于对应的占位符是%f,会读取到.45e12,这是采用科学计数法的浮点数格式,后面的# 不属于浮点数的有效字符,所以会停在这里。

                (e12 是 10的12次方,【.45e12】为 【0.45 × 10的12次方】)

(三)scanf()占位符注意事项

        ① 除了%c 以外,都会自动忽略起首的空白字符。%c 不忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格 如果要强制跳过字符前的空白字符,可以写成scanf(" %c", &ch),即%c 前加上一个空格,表示跳过零个或多个空白字符。

        ② 在C语言的 【scanf 函数】中,【格式控制字符串】中的空格用来【指定跳过输入流中的空白字符(包括空格、制表符和换行符)】
        当你在 " %d " 后加上空格时,会【跳过一个或多个空白字符,然后继续等待输入一个整数】。这意味着,在输入整数前的任何空白字符都会被忽略。所以," %d " 后面的空格可以用来消耗换行符或空格,以便在输入数字后读取到下一个非空白字符。

        注:

                【格式控制字符串】"%d" 只想输入一个数时在后面加空格,它会在你输入整数后,【跳过若干空白字符,继续让你输入一个整数】,但由于只有一个整数会被读取,后面输入的整数没有用,如下演示:

int a = 0;
scanf("%d ", &a);

这里%d后面有空格,会让你输入两次,第二次输入作废,不要这样写

        
         占位符%s,它其实不能简单地等同于字符串。它的规则是,从当前第一个非空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。因为%s不会包含空白字符,所以无法用来读取多个单词,除非多个%s一起使用。这也意味着, scanf () 不适合读取可能包含空格的字符串,比如书名或歌曲名。另外, scanf() 遇到%s 占位符,会在字符串变量末尾存储一个空字符\0。输入多个字符串可以空格分隔,如下:

char str1[10], str2[20], str3[30];
scanf("%s %s %s", str1, str2, str3);

每个"%s"之间都有空格,消除空白字符

        ④ scanf()将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,储存字符串时,很可能会超过数组的边界,导致预想不到的结果。为了防止这种情况,使用%s 占位符时,应该指定读入字符串的最长长度,即写成%[m]s ,其中的[m] 是一个整数,表示读取字符串的最大长度,后面的字符将被丢弃,注意多留一位数组元素给系统自动补上的 "\0" 。

        (区别:printf()限定字符串长度:% [ . 整数 ] s

char name[11];
scanf("%10s", name)

        以上博客内容仅供分享

  • 26
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值