C++读书笔记——4.表达式-创新互联
sizeof 运算符返回一条表达式 或 一个类型名字所占的字节数。sizeof 运算符满足右结合律,其所得的值是一个size_t 类型的常量表达式。
我们是自2013年创立以来的成都网站建设公司,提供网站建设,电商网站设计开发,外贸网站建设,响应式网页设计,小程序设计、等服务。为客户创造有价值的品牌营销体验,让互联网提升企业的竞争力!Person person, * p;
sizeof(Person); //存储Person类型的对象所占空间的大小
sizeof person; //person的类型的大小,即 sizeof (Person)
sizeof p; //指针所占空间的大小
sizeof* p; //p 所指类型的空间大小,即 sizeof (Person)
sizeof person.age; //Person 的 age成员对应类型的大小
sizeof Person::age; //另一种获取age大小的方式
因为 sizeof 不会实际求运算对象的值,所以即使 p 是一个无效(即 未初始化的)指针,也不会有影响。
在 sizeof 的运算对象中解引用一个无效的指针仍然是一种安全的行为,因为指针实际上并没有被真正的使用。sizeof 不需要真正的解引用指针也能知道它所指对象的类型。
- 对char 或 类型为char的表达式执行sizeof运算,结果为1
- 对引用类型执行sizeof运算得到被引用对象所占空间大小
- 对指针执行sizeof 运算得到指针本身所占空间大小
- 对解引用指针执行 sizeof 运算得到指针指向的对象所占空间大小,指针不需要有效
- 对数组执行 sizeof 运算得到整个数组所占空间大小,等价于对数组中的所有元素各执行一次 sizeof 运算 并将所得结果求和。注意:sizeof 运算不会把数组转换成指针处理
- 对 string 对象 和 vector对象 执行sizeof 运算 只返回该类型固定部分的大小,不会计算对象中的元素占用了多少空间。
如果两种类型可以相互转换,那么他们就是关联的。
C++ 不会直接将两个不同类型的值相加,而是先根据类型转换规则设法将运算对象的类型统一后再求值。
发生隐式转换的时机:
- 在大多数表达式中,比 int 类型小的整型值首先提升为较大的整数类型
- 在条件中,非布尔值转换成布尔类型
- 初始化过程中,初始值转换成变量的类型;在赋值语句中,右侧运算对象转换成左侧运算对象的类型
- 如果算术运算 或 关系运算的运算对象有多种类型,需要转换成同一种类型
- 函数调用时也会发生类型转换
算术转换的含义是把一种算术类型转换成另一种算术类型
1. 整型提升整型提升负责把小整数类型转换成较大的整数类型。对于 bool,char,signed char,unsigned char,short 和 unsigned short 来说,只要它们所有可能的值都能存在 int 里,它们就会提升为 int 类型;否则提升成 unsigned int 类型。
2. 无符号类型的运算对象如果某一个运算符的运算对象不一致,这些运算对象将转换成同一种类型。
如果一个运算对象是无符号类型,另一个是有符号类型,而其中的无符号类型 不小于 有符号类型,那么有符号运算对象转换成无符号对象。
如果有符号类型大于无符号类型。如果无符号类型的所有值都能存在该有符号类型中,则无符号类型转换成有符号类型;否则有符号类型转换成无符号类型。
3. 理解算数转换bool flag;
char cval;
short sval;
unsigned short usval;
int ival;
unsigned int uival;
long lval;
unsigned long ulval;
float fval;
double dval;
3.14159L + 'a'; // 'a' 提升成int,然后int值转换为 long double
dval + ival; //ival 转换成 double
dval + fval; //fval 转换成 double
ival = dval; //dval 转换成int (舍去小数部分)
flag = dval; //如果 dval是0 flag为false,否则为true
cval + fval; //cval 提升成 int ,然后 int 再转换成 float
sval + cval; //sval 和 cval 都提升成 int
cval + lval; //cval 转换成 long
ival + ulval; //ival 转换成 unsigned long
usval + ival; //根据 unsigned short 和 int 所占空间的大小进行提升
uival + lval; //根据 unsigned int 和 long 所占空间的大小进行转换
2. 隐式类型转换数组转换成指针: 在大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针。
当数组被用作 decltype 的参数,或者作为取地址符 & ,sizeof 以及 typeid 等运算符的对象时,不会发生转换。
指针的转换: 常量整数0 或 字面值nullptr 能转换成任意指针类型;指向任意非常量的指针能转换成 void*;指向任意对象的指针能转换成 const void*
转换成布尔类型:如果指针或算数类型的值为0,转换结果是false;否则为true
转换成常量: 允许将指向非常量类型的指针转换成指向相应常量类型的指针,对于引用也是这样。
int i;
const int& j = i; //非常量转换成 const int 的引用
const int* p = &i; //非常量的地址转换成const 的地址
int& r = j, * q = p; //错误: 不允许const 转换成非常量
类 类型定义的转换:类 类型定义由编译器自动执行的转换,不过编译器每次只能执行一种类 类型转换
3. 显式转换有时我们希望显式的将对象强制转换为另一种类型。虽然有时不得不使用强制类型转换,但这种方法本质上是非常危险的。
static_cast任何具有明确定义的类型转换,只要不包含顶层 const ,都可以使用 static_cast。
int i, j;
double slope = static_cast(j) / i; //强制类型转换以便执行浮点数除法
当需要把一个较大的算术类型 赋值给一个较小的类型时,static_cast 非常有用。
static_cast 对于编译器无法自动执行的类型转换也非常有用。例如:我们可以使用 static_cast 找回存在于 void* 指针中的值:
int d = 3;
void* ptr = &d;
double* dp = static_cast(ptr);
强制转换的结果将与原始的地址相等。因此我们必须确保转换后所得的类型就是指针所指的类型。
const_castconst_cast 只能改变运算对象的底层 const
const char* pc;
// 正确: 但是通过 p 写值是未定义的行为
char* p = const_cast(pc);
对于常量对象转换为非常量对象的行为,一般称之为“去掉const性质”。
如果一个对象是 const 常量,再使用const_cast 执行写操作就会产生未定义的后果。
只有 const_cast 能改表表达式的常量属性,使用其他的 命名强制类型转换 改变表达式的常量属性都将引发编译器错误。
const char* cp;
//错误: static_cast 不能转换掉 const属性
char* q = static_cast(cp);
static_cast(cp);
//错误: const_cast 只改变常量属性
const_cast(cp);
reinterpret_castreinterpret_cast 通常为运算对象的位模式提供较低层次的重新解释。
int* ip;
char* pc = reinterpret_cast(ip);
//这一句在运行时就会发生错误
string str(pc);
reinterpret_cast 本质上依赖于机器。要想安全的使用 reinterpret_cast 必须对涉及 类型 和 编译器实现转换的过程都非常了解。
建议:尽量避免强制类型转换。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
当前标题:C++读书笔记——4.表达式-创新互联
转载来于:http://myzitong.com/article/epjjh.html