三、基本数据类型和计算(二)

1、字符
#include <iostream>int main(){	std::cout << 65 << std::endl;       //65是一个int类型的整数	std::cout << (char)65 << std::endl;    //将其转化为1个字节的char类型字符,编码的正向操作	std::cout << (int)'A' << std::endl;   //编码的逆向操作,将字符转化为数字}

1)字符数据原理

内存数据编码规范显示
65ASCIIA

原理:在内存中最终存储的数据都是数字,字符本质上还是数字,显示什么样的形式,取决于编码规范的实现,上述代码中编码规范的实现是由std::cout类决定的。

ANSI

2)字符数据类型

类型内存占用说明
char1ascii字符
wchar_t2/4宽字节字符,使用L来说明变量
char16_t2utf_16字符,使用一个u来说明变量
char32_t4utf_32字符,使用一个U来说明变量

①chat类型

#include <iostream>int main(){	char charA{ 'A' };  //使用字符初始化字符,编译器会将字符强制转化为数字	std::cout << charA << std::endl;	char charB{ 66 };	std::cout << charB << std::endl;     //使用数字的方式初始化字符串		charB++;	std::cout << charB << std::endl; //因字符本质为数字,所以可以进行计算}

②wchar_t类型

该类型占用两个字节(无论是汉字、数字、字符),因编译器不同,占用的字节数不同(2字节或4字节),定义字符时要通过L来说明字符是一个宽字节字符

#include <iostream>       //#include <locale>    //设置本地,显示中文需要包含该头文件int main(){	setlocale(LC_ALL, "chs");	wchar_t wcharA{ L'A' };       //定义时使用L进行说明	wchar_t wcharB{ L'我' };	std::wcout << wcharA << std::endl;  //std::cout没有实现对宽字节的编码 	std::wcout << wcharB << std::endl;	std::cout << "wchar_t的内存大小为:"<< sizeof(wcharA) << std::endl;}

④char32_t、char16_t

为实现跨平台的应用,引入了char32_t、char16_t,因为wchar_t因平台不同占用的内存不同

#include <iostream>       //#include <locale>    //设置本地,显示中文需要包含该头文件int main(){	char16_t char16{ u'a' };	std::cout << char16 << std::endl;  //std::cout和std::wcout都没有实现对char16_t的编码,因此只能输出数字	char32_t char32{ u'a' };	std::cout << char32 << std::endl; //std::cout和std::wcout都没有实现对char32_t的编码,因此只能输出数字}

3)ASCII编码表

换行可以使用char(10)表示

//换行#include <iostream>       int main(){	std::cout << "Hello World!!" << char(10);}

4)练习:用户输入一个小写字母,转化为大写字母后输出

//用户输入一个小写字母,转化为大写字母后输出#include <iostream>int main(){	char userIn;	std::cout << "请输入一个小写字母:";	std::cin >> userIn;	userIn -= 32;	std::cout << "转化后的大写字母为:" << userIn << std::endl;}
2、推断类型

即不告诉编译器使用什么数据类型

1)auto类型

类型定义语法示例
auto 变量名 {初始值};变量类型查看函数
typeid(变量).name
#include <iostream>

int main()
{
	auto num{ 100 };
	auto charUser{ U'a' };     //auto类型的变量必须初始化
	auto chat_z{ u'A' };

	std::cout << "num的类型为" << typeid(num).name() << (char)10;
	std::cout << "charUser的类型为" << typeid(charUser).name() << (char)10;
	std::cout << "chat_z的类型为" << typeid(chat_z).name() << (char)10;
}

注:日常不推荐使用auto类型,因为代码阅读性不好

3、格式化输出流及转义

1)格式化输出流操作

作用:使用文字输出更美化

注:加粗内容需要使用头文件<iomanip>

格式化输出流 含义 示例
std::fixed 以小数点模式输出浮点数 3.1415926
std::scientific 以科学计数法输出小数 3E100
std::defaultfloat 恢复默认的小数输出,即将上述2个设置取消
std::setprecision(int) 设置小数精度 std::setprecision(2),输出3.14
std::dec 以后输出的数字采用十进制输出 999
std::hex 以后输出的数字采用十六进制输出 FFF
set::oct 以后输出的数字采用八进制输出 777
std::showbase 十六进制和八进制显示前缀 0xFF
std::shownobase 关闭十六进制和八进制显示前缀
std::setw(int) 把输出内容设置宽度,每次都需设置 std::setw(10)输出 999
std::setfill(char) 当显示宽度超过字符快宽度时,用指定字符串填充剩余内容 **************999
std::left 设置字符对其模式为左对齐
std::right 设置字符对其模式为右对齐
//格式化输出及转义

#include <iostream>
#include <iomanip>

int main() {
	std::cout << std::fixed;  //以小数点计数
	std::cout << 3.1415926 << (char)10;

	std::cout << std::scientific;//以科学计数法技术
	std::cout << 3.1415926 << char(10);

	std::cout << std::setprecision(2);  //设置小数精度
	std::cout << 3.1415926 << std::endl;

	std::cout << std::hex; //以16进制输出
	std::cout << 100 << std::endl;

	std::cout << std::oct; //以8进制输出
	std::cout << 100 << std::endl;

	std::cout << std::dec; //以10进制输出
	std::cout << 100 << char(10);

	std::cout<<std::setw(10)  << 2222 << std::endl;     //设置输出宽度
	//当显示宽度超过字符宽度时,剩余部分使用特定字符填充
	std::cout << std::setfill('*') << std::setw(10) << 999 << std::endl; //

	std::cout << std::right; //右对齐
	std::cout << "helloworld" << std::endl;

}

//输出内容

2)转义

转义序列 作用
\n 换行
\\ \
' '
\t 制表符
" "
? ?
\b 退格
\a 警告声
4、运算优先级

1)运算优先表

注:下表运算符从上到下依次优先运算

运算符 关联性
:: 左(从左往右计算)
() [] -> . 后缀++ 前缀-- typeid const_cast dynamic_cast static_cast reinterpret_cast 左(从左往右计算)
! ~ 一元+ 一元- 前缀++ 前缀-- & * (类型)sizeof new new[] delete delete[] 右(从右往左计算)
.* ->* 左(从左往右计算)
* / % 左(从左往右计算)
+ - 左(从左往右计算)
<< >> 左(从左往右计算)
< <= > >= 左(从左往右计算)
== != 左(从左往右计算)
& 左(从左往右计算)
^ 左(从左往右计算)
| 左(从左往右计算)
&& 左(从左往右计算)
|| 左(从左往右计算)
? : op= 右(从右往左计算)
throw 右(从右往左计算)
. 左(从左往右计算)

2)a++和++a的反汇编

#include <iostream>
int main()
{
	int a{ 10 };
	a++;
	++a;

	int b{ 5 };
	int c{};

	c = b + a++; //c=b+a;a=a+1  //后缀优先

	c = b + ++a; //a=a+1;c=b+a
	
	c = 3 * -b++ + a;        //正负在前,乘除、加减在后
	std::cout << c << std::endl;
	c = 2 * -b-- - a;
	std::cout << c << std::endl;
}

①查看汇编的方法:先设置断点,调试->窗口->反汇编

②a++和++a反汇编代码

结论:++a和a++在不执行其他操作的时候,一样

③c = b + a++和c = b + ++a汇编区别