【共读Primer】8.<2.1> 基本内置类型(2) Page32

虽然C++中的类型是强制声明的,但是这并不意味着不同类型之间不可以进行一些计算或赋值。

我们来看下面的一组代码

 1 #include <iostream>
 2
 3 int main()
 4 {
 5     bool b = 42;
 6     int i = b;
 7     double pi = i;
 8     unsigned char c = -1;
 9     signed char c2 = 256;
10     std::cout << "bool b =" << b
11     << "\nint i =" << i
12     << "\ndouble pi =" << pi
13     << "\nunsigned char c =" << (int)c
14     << "\nsigned char c2 =" << (int)c2;
15 }

上面的赋值语句中,没有一个是在把对应的值赋值给对应的类型。

但是并没有产生编译的错误,我们曾经说过,C++是一种强类型的语言。

这样胡乱的赋值感觉并不是强类型啊!

事情是这样的,类型指一个变量的类型,在声明的时候已经确定下来,在一定作用域内是不可以对类型进行改变的。

而类型之间可以赋值,是一种C++的特性,它称之为类型转换。

转换规则如下(敲黑板,记重点):

1. 非bool型赋值给bool型,0为false,其它为true

2. bool型赋值给非bool型,true为1,false为0

3. 把整形赋值给浮点型,整数部分相同,小数部分为零

4. 超过无符号类型的表示范围的赋值,取赋值数与该类型可表示最大数后为当前结果

5. 给带符号类型一个超出范围的值,结果是未定义的

虽然类型转换在很大程度上给了我们方便,但是这种方便却伴随着一些危险,比如以下程序:

1     int a = 42;
2     if (a = 12) // 大家请注意这里,我觉得这种代码想要表达的意思应该是比较,而不是赋值,所以这里应该是a == 12
3     {
4         std::cout << "\nis true" << std::endl;
5     }
6     else
7     {
8         std::cout << "\nis false" << std::endl;
9     }

将这段代码并入上一段程序中共同编译运行,结果如下:

大家看一下代码的运行结果,少些一个=号,从编译到运行都没有问题,但是结果却不是我们想要的。

所以大家一定要深刻的掌握类型转换的过程,特别是编译器自作主张给我们做的转换,如果不知道什么原因是非常危险的。

另外分享一个小技巧:上述情况想要避免很容易,把常量写在=的前面  if ( 12 == a ) 这样写就不会出现我们刚才描述到的现象。

因为如果在这种情况下你只写了一个等式,那么会有编译错误,根本无法生成可执行文件

在上一章的内容中我们了解到了无符号类型和有符号类型,那么关于这两种的类型转换会有什么样的转换过程需要去注意

下面还是来看一段代码,然后我们在分析一下:

 1     unsigned int u = 10;
 2     int i = 42;
 3     std::cout << "i + i = "<< i + i << std::endl;    // 结果正确
 4     std::cout << "u + i = " << u + i << std::endl;    // 结果为 4294967264
 5
 6     unsigned int u1 = 42, u2 = 10;
 7     std::cout << "u1 - u2 = "<< u1 - u2 << std::endl;    // 结果正确
 8     std::cout << "u2 - u1 = "<< u2 - u1 << std::endl;    // 结果正确但是是取模后的值
 9
10
11
12     for (int i = 10; i >=0; --i) // 一个正常的循环,循环10次结束
13     {
14         std::cout << i << std::endl;
15     }
16
17     for (unsigned int i = 10; i >=0; --i) // 一个死循环,i永远无法小于零,所以一直循环
18     {
19         std::cout << i << std::endl;  
20     }
21     

如果要编译以上代码,记得将无限循环注释掉,或者给一个循环退出条件。

无符号类型与有符号类型负数相加,首先吧负数转换为无符号,然后相加,所以的数非常的大

当从无符号书中减去一个值时,不管这个值是什么都必须确保不能是一个负数

所以这里给大家的一个忠告,一定要记住,带符号和无符号的千万不要一起进行运算。

 1 20 /*十进制数*/
 2 024 /*八进制数*/
 3 0x14 /*十六进制数*/
 4
 5 //浮点型可以用科学计数法表示
 6 3.14159   3.14159E0   0.   0e0   .001
 7
 8 // 用引号括起来的是字符,双引号括起来的是字符串
 9 ‘a’    // 字符字面值
10 "Hello World!" // 字符串字面值
11
12 // 转移序列
13
14 \n // 换行符
15 \v // 横向制表符
16 \\ // 反斜线
17 \r // 回车符
18 \t // 横向制表符
19 \b // 退格符
20 \? // 问号
21 \f // 进纸符
22 \a // 报警符
23 \" // 双引号
24 \‘ // 单引号
25
26 // 指定字面值的类型
27 L‘a‘ // 宽字符型字面值,类型是wchar_t
28 u8"hi!" // utf-8自穿穿字面值
29 42ULL // 无符号整形字面值,类型是unsigned long long
30 1E-3F // 单精度浮点型字面值,类型是float
31 3.14159L // 扩展精度字面值,类型是long double
32
33 // bool 字面值
34 true  false
35
36 // 指针字面值
37 nullptr

以上这些都是字面值类型以及写法。

原文地址:https://www.cnblogs.com/ChattyKu/p/9410757.html

时间: 2024-07-29 19:47:00

【共读Primer】8.<2.1> 基本内置类型(2) Page32的相关文章

【共读Primer】58.[6.5]参数匹配 Page217

一般来说函数的选择是比较明确的事情,因为有着参数类型和参数数量的标准. 但是如果将类型转换和默认参数都加入到重载函数中,这个过程就变的复杂起来. 来看看一下代码: void f(); void f(int); void f(int ,int); void f(double, double = 3.14); 在函数的选择过程中分为两步: 1. 找到当前作用域可见的所有名称相同的函数 2. 找到参数数量相等且类型相同或可转换的函数 f(5.6); // 调用 void f(double, doubl

【共读Primer】35.&lt;5.2&gt;语句作用域 Page155

在if .switch. while 和for语句的控制结构内定义的变量只在其结构内部可见,超出结构范围将变为未定义. 1 #include <iostream> 2 #include <vector> 3 4 using std::cout; 5 using std::endl; 6 7 std::vector<int> v = {1,2,3,4,5,6,7,8,9}; 8 9 10 int get_num() 11 { 12 return 1; 13 } 14 15

【共读Primer】53.[6.4]函数重载 Page207

在同一个作用域内,几个函数名字相同但形参列表不同,我们成为重载(voerloaded)函数. void print(const char *cp); void print(const int *beg, const int*end); void print(const int ia[], size_t size); int j[2] = {0, 1} print("Hello World"); print(j , end(j) - begin(j)); print(begin(j) -

【共读Primer】3.&lt;1.3&gt;注释简介 Page8

C++的注释有两种 1.  双斜杠开始到本行结束 (//) 2. 斜杠星开始 星斜杠结束 (/*)(*/) 1 #include <iostream> // 标准库中输入输出流的库名称 2 /* 3 * 简单主函数: 4 * 读取两个数,求它们的和 5 */ 6 int main() 7 { 8 std::cout << "Enter two numbers:" << std::endl;// 输出一个提示信息的字符串,并在结尾换行 9 int v1

【共读Primer】10.&lt;2.3&gt; 复合类型 Page45

C++的复合类型 引用和指针 引用就像是类型的别名 int ival = 1024; int &refVal = ival; // int &refVal2 ; // 报错:引用必须被初始化 int &refVal1 = ival, &refVal2 = ival, &refVal3 = refVal1, Val4=ival; // refVal1/refVal2/refVal3都是引用,其中refVal3用另一个引用进行初始化 // Val4是一个int它并不是引

【共读Primer】19.&lt;3.5&gt; 数组-C风格字符串 Page109

C风格的字符串是指以空字符'\0'结尾的一个字符串. 这种字符串虽然在C++中兼容,但是极易引起内存安全问题,所以不建议使用. 但是作为一个语言特性,我们应该了解它,这样才能在碰到的时候做到心中有数. 3.5.4 C标准库string函数 这里所说的string函数并不是std::string的函数,而是在C的标准库中,对C风格字符串进行操作的一些全局函数. strlen(p); //计算p的长度,不计入空字符结尾 strcmp(p1, p2); // 比较两个字符串p1和p2是否相等,相等返回

【共读Primer】20.&lt;3.6&gt; 多维数组 Page112

C++中的多位数组,严格来说是数组的数组. int ia[3][4]; //大小为3的数组,每个元素是含有4个整数的数组 // 大小为10的数组,每个元素都是大小为20的数组, // 这些数组的元素是含有30个整数的数组 int arr[10][20][30] = {0}; // 将所有元素初始化为 0 初始化多维数组 int ia1[3][4] = { {0,1,2,3}, {4,5,6,7}, {8,9,10,11} }; // 以下语句等价于上面的初始化 int ia2[3][4] = {

【共读Primer】27.&lt;4.7&gt;条件运算符 Page134

条件表达式,判断第一个表达式的真假,如果为真,返回冒号左侧的结果,如果为假返回冒号右侧的结果 (a> b ?  a : b) string finalgrade = (grade < 60) ? "fail" : "pass"; // 如果grade小于60则返回fail,否则返回pass 条件运算符的嵌套 // 如果grade值90以上,返回"high pass" ,否则看是否小于60,小于则返回fail,大于等于则返回pass f

【共读Primer】26.&lt;4.6&gt;成员访问运算符 Page133

成员访问运算符: . 点运算符 -> 箭头运算符 string s1="a string", *p = &s1; auto n = s1.size(); // 运行string对象s1的size成员 n = (*p).size(); // 运行p所知对象的size成员 n = p->size(); // 等价于(*p).size() 因为皆因用运算符的优先级低于点运算符,所以执行解引用运算的子表达式两端必须加括号. 如果不加括号则含义会不同 // 含义是:运行p的s