C++数据类型
C++定义了算数类型和空类型在内的基本数据类型。空类型不对应具体的值,仅用在特殊场合,如:函数返回值
编码
字符集:Unicode字符集包括世界上几乎所有语言所需的字母、数字、标点符号和符号,是一个庞大的字符集合。
编码方案:Unicode定义了几种字符编码方案,包括UTF-8、UTF-16和UTF-32等。这些编码方案用不同的方式来将Unicode代码点编码为字节序列,以适应不同的应用场景。
UTF-8:一种变长编码方案,使用1到4个字节来编码不同的Unicode代码点,可以有效地节省存储空间,并且完全兼容ASCII码。
UTF-16:一种定长编码方案(但存在变长情况,用于表示超出基本多文种平面的字符),通常使用2个字节来表示字符,但也可以扩展到4个字节来表示超出基本多文种平面的字符。
UTF-32:一种定长编码方案,使用4个字节来表示每个Unicode字符。UTF-32虽然简单明了,但占用空间较大,因此使用相对较少。
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码):ASCII码使用指定的7位或8位二进制数组合来表示128或256种可能的字符。标准ASCII码,也称为基础ASCII码,使用7位二进制数(剩下的1位二进制为0)来表示所有的大写和小写字母、数字0到9、标点符号,以及在美式英语中使用的特殊控制字符。这些字符共128个,包括33种控制字符和95种可显示字符。
GBK:GBK编码采用双字节表示一个字符。GBK编码兼容GB2312编码和ASCII编码。在GBK编码下,英文字母、数字、标点等非汉字字符仍然只占用一个字节,其编码值与ASCII码相同。同时,GB2312中的汉字可以直接使用GBK编码解码。GBK编码收录了包括繁体字在内的众多汉字、特殊字符和控制字符。综上所述,GBK编码是一种针对中文字符集的字符编码方式。
GBK与UTF-8编码的比较:UTF-8编码是一种变长编码方式,能够更节省存储空间,并且支持全球几乎所有的文字。相比之下,GBK编码是一种固定长度编码(每个字符占两个字节),在处理大规模数据时可能导致存储成本增加。此外,UTF-8编码是Unicode编码的一种存储方式,具有更强的兼容性和国际化支持。因此,在全球化应用中,UTF-8编码的优势更加明显。
算数类型
分两类:整形和浮点型
C++标准规定了类型的最小值,就是允许编译器赋予这些类型更大的值
C++语法规定:一个int至少和一个short一样大,一个long至少和一个int一样大,一个long long至少和一个long一样大!
了解:wchar_t类型用于确保可以存放机器最大扩展字符集中的任意一个字符,类型char16_t和char32_t则为Unicode字符集服务(Unicode是用于表示所有自然语言中字符的标准)。
带符号和无符号
除去布尔型和扩展的字符型之外,其他整型可以划分为带符号的(signed)和无符号(unsigned)两种。带符号类型可以表示正数、负数或0,无符号类型则仅能表示大于等于0的值。
类型int、short、long和long long 都是带符号的,通过在这些类型名前添加unsigned 就可以得到无符号类型,例如 unsigned long。类型unsignedint可以缩写为unsigned。
类型转换
当不同的数据类型在一起运算或者相互赋值的时候,就需要进行数据类型转换。转换规则就是“小转大”自动进行,“大转小”需要强制执行。这里的“大”和“小”指的是对应数据类型占用范围。
自动转换方向:
①当一个操作数是char或short时,它们会被提示为int类型。如果int不能表示char或short的值,则会提升为unsigned int
②int和unsigned int参与运算时,结果通常会被提升为unsigned int。当整数和浮点数参与运算时,整数会被提升为浮点数类型(如float、double)。
③整数类型也可以隐式转换为布尔类型,0转换为false,非0值转换为true。
查看数据的类型
using namespace std;
#include <iostream>
#include <typeinfo>
int main() {
int a = 5;
long b = 10;
auto c = a + b;
cout <<typeid(c).name();//long
return 0;
}
using namespace std;
#include <iostream>
#include <typeinfo>
int main() {
int a = 5;
float b = 10;
auto c = a + b;
cout <<typeid(c).name();//float
return 0;
}
强制类型转换
格式:(new_type_name) expression
,其中 new_type_name
为新类型名称,expression
为表达式
int main() {
int a = 5;
double d = (double)a;
return 0;
}
无论是自动的类型转换还是强制类型转换,都只是为了本次操作或运算而进行的临时转换,转换的结果也会保存到临时的内存空间内,不会改变数据本来的类型或者具体的值!
在C++语言中新增了四个用于强制类型转换的关键字,分别是:static_cast、 dynamic_cast, const_cast、 和 reinterpret_cast,使用语法为 xxxx_cast<new_type_name>(expression)。
相比于C语言中使用小括号()
来完成强制类型转换,C++中这几个关键字的引入能更清晰的表明它要完成强制类型转换的意图。
static_cast
static_cast
是最常用的类型转换操作符,用于在具有明确关系的类型之间进行转换。
它主要用于以下几种情况:
基本数据类型之间的转换:例如,将 int
转换为 double
,或者将 float
转换为 int
。
有继承关系的类之间的转换:可以将派生类对象的指针或引用转换为基类对象的指针或引用,反之亦然(但仅限于安全向下的转换,即指向派生类对象的基类指针或引用转换为派生类指针或引用时,这种转换在运行时不会进行类型检查)。
*void 与其他指针类型之间的转换**。
int a = 5;
double b = static_cast<double>(a); // 基本数据类型之间的转换
Base* basePtr = new Derived();
Derived* derivedPtr = static_cast<Derived*>(basePtr); // 基类指针转换为派生类指针(需确保转换是安全的)
dynamic_cast
dynamic_cast
主要用于在类的继承体系中进行安全的向下转换(即将基类指针或引用转换为派生类指针或引用)。这种转换在运行时进行类型检查,如果转换不成功,将返回 nullptr
(对于指针)或抛出 std::bad_cast
异常(对于引用)。
dynamic_cast
只能用于带有至少一个虚函数的类(多态类型)。
Base* basePtr = new Derived();
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);
if (derivedPtr) {
// 转换成功
} else {
// 转换失败
}
const_cast
const_cast
用于添加或移除 const
限定符。它通常用于修改原本不应被修改的对象(虽然这种做法并不推荐,因为它破坏了 const
的设计意图)。
const int* constPtr = &someValue;
int* nonConstPtr = const_cast<int*>(constPtr); // 移除 const 限定符
const std::string* constStrPtr = new std::string("Hello");
std::string* nonConstStrPtr = const_cast<std::string*>(constStrPtr); // 移除 const 限定符
reinterpret_cast
reinterpret_cast
是最强大但也最危险的一种类型转换。它几乎可以转换任何类型的指针或引用为任何其他类型的指针或引用,不进行任何类型检查。它通常用于底层编程,例如与C语言代码交互或操作硬件。
由于 reinterpret_cast
可能导致未定义行为,因此应谨慎使用。
int a = 5;
void* voidPtr = &a;
int* intPtr = reinterpret_cast<int*>(voidPtr); // 将 void* 转换为 int*
double d = 3.14;
int* reinterpretedPtr = reinterpret_cast<int*>(&d); // 强制将 double* 转换为 int*(通常是不安全的)
原文地址:https://blog.csdn.net/m0_62407354/article/details/143607184
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!