书接上回
一.相关概念
1.数据类型
C++中提供了丰富的数据类型来描述⽣活中的各种数据。⽐如:可以使⽤整型类型来描述整数,使⽤字符类型来描述字符,使⽤浮点型类型来描述⼩数
所谓类型,就是显示数据所具有的共同特征的抽象,编译器只有知道了数据的类型才知道怎么操作数据
下面探讨简单数据类型(内置数据类型)
1.1字符型
在前攀升可以敲出各种字符,如a % &等,这些符号被称为字符,用单引号括起来,如:'a',为了能说明这些字符,抽象出来一种类型,就是字符型char
ASCII编码
计算机中所有数据都是二进制形式存储的,那字符是怎么以二进制形式存储的呢?如果我们每个人都给字符中的每个字符编一个二进制序列就乱套了,所以了⽅便⼤家相互通信,不造成混乱,后来美国国家标准学会(ANSI)出台了⼀个标准ASCII编码,C语言中的字符就遵循了ASCII编码的方式
参考:https://zh.cppreference.com/w/cpp/language/ascii
我们可以记忆一些关键的字符
字符A~Z:65-90;
字符a~z:97-122;
对应的小写字母的码值比大写字母大32;
数字字符0~9:48-57;
\n:10;
ASCII码值从0~31这32个字符是不可打印字符,无法打印在屏幕上观察
#include<iostream>
using namespace std;
int main()
{
char c1 = 'Q';
cout << c1 << endl;
char c2 = 81;
cout << c2 << endl;
return 0;
}
输入对应的ASC码值,得到相应字符,证明内存中字符以对应的ASC码的二进制形式存储
1.2整型
整型类型是对所有整数的抽象,为了能对整数形成统⼀的类型标识,就有整型;
c/c++中整形分成四大类:short 短整型,int整型, long长整型, long long更长的整型(后面跟着的int可以省略)
1.3浮点型
浮点型式对所有实数(⼩数)的抽象,为了能对实数进⾏统⼀的类型标识,就有了浮点型。
浮点型有三种:float 单精度浮点型;double 双精度浮点型;long double 更长的双精度浮点型
注:在C/C++中⼩数的书写形式
3.14;//编译器默认识别成double
3.14f;//加f识别成float
1e5;//科学计数法形式:表示1.0*10^5
1e5+10;//1.0*10^5+10=100010
1.23e5+10;//123010
1.4布尔类型
变量取值只有true和false(只能给bool类型的变量赋予这两个值),用来专门表示真假的,当然,也可以不用这个类型实现同样的效果
// 使用布尔类型
int main()
{
bool flag = true;
if (flag)
printf("I like C++!\n");
return 0;
}
//不使用
int main()
{
int flag = 0;
cin >> flag; //如果输⼊⾮零的值,flag就表⽰真
if (flag)
printf("I like C++!\n");
return 0;
}
1.5signed和unsigned
这两个关键字是修饰字符型和整型类型的,浮点型和布尔类型不能用这个修饰!
signed关键字,表示一个类型带有正负号,包含负值;
unsigned关键字表示该类型不表示负数,只表示0和正整数;
在他们的修饰下,字符和整型类型其实更加丰富,可以有以下这些:
对于int类型,默认带有正负号,也就是int=signed int,所以signed可以不写
int类型也可以不带正负号,只表示非负整数。这时就必须使用关键字unsigned
unsigned int的int也可以省略~
直观上理解,使用unsigned声明变量,同样⻓度的内存能够表⽰的最⼤整数值,增⼤了⼀倍。
当然,为什么取这些值,后面关于数据在内存中的存储会有介绍
对于char类型,情况有些不同:
就是说:明确了字符类型的符号的时候,signed char的signed不能省略,因为char不一定等于signed char 取决于编译器的实现,大部分编译器上是char=signed char
2.数据类型长度
每⼀种数据类型都有⾃⼰的⻓度,使⽤不同的数据类型,能够创建出⻓度不同的变量,变量⻓度的不同,存储的数据范围就有所差异。
2.1sizeof操作符
sizeof是关键字,也是操作符,专门计算特定数据类型长度,单位字节,操作数可以是类型,也可以是变量名或表达式,sizeof的操作费不是类型而是表达式的时候,可以省略括号。
sizeof后边的表达式是不真实参与运算的,根据表达式的类型来得出大小:例如sizeof(a=b+c),无论bc是什么类型,最终返回的都是a的类型所对应的大小;sizeof(b+1.000000),会按照更高级的变量计算大小。
拓展,size_t类型
2.2各种数据类型长度
#include <iostream>
using namespace std;
int main()
{
cout << sizeof(char) << endl;
cout << sizeof(bool) << endl;
cout << sizeof(short) << endl;
cout << sizeof(int) << endl;
cout << sizeof(long) << endl;
cout << sizeof(long long) << endl;
cout << sizeof(float) << endl;
cout << sizeof(double) << endl;
cout << sizeof(long double) << endl;
return 0;
}
输出结果:devC++下:
该如何理解这些数据类型的⻓度呢?其实我们使⽤这些数据类型可以向内存申请空间(就是创建变 量),不同的数据类型⼀次性申请的空间⼤⼩是有差异的。你可以这样理解:
2.3各类型取值范围
前⾯的知识已经让我们了解到了很多的数据类型,不同的数据类型所创建的变量的长度是有差异的, 这个长度差异又决定了,这种变量中能存储的值的大小。 其实每⼀种数据类型有自己的取值范围,也就是存储的数值的最大值和最小值的区间,有了丰富的类型,我们就可以在适当的场景下去选择适合的类型。下面是不同数据类型的取值范围。
这些符号在包含头文件climits,cfloat的时候就可以使用了
大家对这些类型的取值范围还得大概知道取值范围的数量级,像 int 类型取值大概就 是:-2.1*10^9~2.1*10^9,这⾥就是10^9这样的数量级。
2.4typedef
用以给变量重命名,以提升竞赛中编码速度,对于复杂的指针类型和自定义类型都很常用
练习:输入一个ASC码值并输出对应字符(非常重要!!!)
我们要知道,无论是c还是c++,你都不能直接把65这样的值直接给ch这个字符变量,因为在读取的时候,scanf和cin都会只读取与类型对应的部分,他会把65当成字符6和字符5,后面的字符5根本没机会读取到,所以打印的是错误的值
3.变量和常量
3.1变量初始化:创建的时候就给一个初始值
int age;
age=5;
这不是创建的时候就赋值,所以这只是单纯赋值,不叫初始化
3.2变量分类
全局变量:大括号外部定义的(共享单车)使用范围广,可以在整个工程内使用
局部变量:大括号内部定义的变量(自己家的车)使用范围比较局限,只能在自己的局部范围内使用
局部变量,全局变量名字相同时,优先使用局部变量,在C++中,如果m变量重名,但是你想使用全局m变量,::m,这样在变量名前加两个:就是使用全局变量了
关于初始化
全局变量:在定义时就被初始化,如果没有初始化,默认初始化为0;
局部变量:通常不会自动初始化,需要在使用前明确的赋值或初始化,否则他们的值将是未定义的,使用未初始化的局部变量可能导致不可预测的行为或运行时错误,因此局部变量建议初始化
提示:如果一个题目即可以使用全局变量,又可以使用局部变量,那怎么选择呢
在竞赛中:能使用全局变量就不适用局部变量:
1.变量不需要初始化,默认初始化为0,这样写比较快
2.很多时候避免传参,因为全局变量哪里都可以用
所以在在竞赛中其实哪种⽅便就使⽤哪种,全局变量的使⽤很常⻅。
但是在企业⾥软件开发的⼯程实践中⼀般建议:能使⽤局部变量的,尽量少使⽤全局变量。 因为企业级的开发,代码量⽐较⼤,全局变量在任意地⽅都可以使⽤,这样就变得不可控了。
3.3常量分类:
字面常量; #define定义常量; const定义常量
a字面常量:
整型常量:各种进制的数字,8进制以0开头,16进制以0x开头
字符常量:‘a’
浮点型常量:3.14,1e6
b#define定义常量
特点:define定义的常量不关注类型,只关注常量的名字和值,编译处理的时候直接替换,在出现常量名字的地方,统统换成常量的内容。
代码举例
#include <iostream>
using namespace std;
#define M 100
#define CH 'x'
#define PI 3.14159
int main()
{
cout << M << endl;
cout << CH << endl;
cout << PI << endl;
return 0;
}
编译器替换后就是:
#include <iostream>
using namespace std;
int main()
{
cout << 100 << endl;
cout << 'x' << endl;
cout << 3.14159 << endl;
return 0;
}
cconst定义的常量
这种定义方式有具体的类型,比define更严谨
#include <iostream>
using namespace std;
const double PI = 3.14159;
int main()
{
int r = 0;
cin >> r;
cout << "
周⻓:
" << 2 * PI * r << endl;
cout << "
⾯经:
" << PI * r * r << endl;
}
//PI = 3.14;//
这种写法是错误的,常量不能被修改
return 0;
习惯上,这种常量的名字一般大写,普通变量的名字不会全⼤写,这样就可以做⼀个区分。
好处:
增加程序可读性;做到可维护性,一改全改,这样使用的地方可以全部改变;常量不可修改,const定义的常量自然也不能修改
在竞赛的时候,我们更习惯于const修饰变量
完