【计算机本科补全计划】C++ Primer 第二章 【变量和基本类型】

正文之前

C++的数据类型包括 算术类型(int double等)和空类型(void),今天发生了一些很可怕的事情,详情请看正文之后!!我好害怕!!

正文

1、 算数类型

算数类型包括:整形和浮点型

  • 整形又分为有符号的和无符号的,有符号的为默认,无符号的需要声明 unsigned。类型char表现于这两种的哪种取决于编译器的类型
  • 选用类型的几点建议:
  • 明确知晓不会小于0时,选择无符号数
  • 使用int时,如果超出了取值范围,那么用long long
  • 浮点运算的时候请选用double 因为float的精度通常不够!而且性能开销相差不大
2、 类型转换
  • 编译器可以自动的转换类型, 也有强行转换类型的:
代码语言:javascript
复制
bool b=42;  //  b为真
int i=b;   //  i=1
i=3.14;   //  i=3
double pi=i;  //   pi的值是3.0
unsigned char c=-1;   // 假设char占8bits,那么c的值是255,而不是-1;
signed char c2=256;   // 假设char占8bits 那么c2的值是未定义的
  • 上面几种都是不会报错的类型转换,另外还有很多形式的类型转换, 如果你都想知道,那么就把你想到的都写出来实验一遍就好了!我就不负责后续了。
  • 另外,程序要尽量避免对实现环境的依赖,比如如果把int看做一个定长的类型,那么这个程序就是不可移植的!
  • 对无符号类型的表达式
    • 如果对一个无符号数赋值一个负数,那么计算机会对这个负数进行无符号数的解答。就好比上面的倒数第二句:
代码语言:javascript
复制
unsigned char c=-1;   // 假设char占8bits,那么c的值是255,而不是-1;
  • 如果char是8bit那么其无符号数的范围就是0 ~ 255,如果是有符号数,那么就是-128 ~ 127 所以上面对无符号数赋值负数,解读为正数就是255 而不是-1; 也许我们不会这么做,但是如果进行算术操作,计算机会自动的把有符号数转换为无符号数进行计算,已达到类型匹配的目的。所以不得不防!!
代码语言:javascript
复制
#include <iostream>    
using namespace std;

int QuanJu=32;

int main()
{

unsigned u=10,u1=42;
cout&lt;&lt;u1-u&lt;&lt;endl;
cout&lt;&lt;u-u1&lt;&lt;endl;
return 0;

}

结果如下:

  • 另外,你有时候可能会无意间造成死循环,比如下面的函数
代码语言:javascript
复制
for (unsigned i = 10; i >=0; --i)
{
cout<<i<<endl;
}

在上面的函数中,你永远也到不了-1,因为无符号数本身的定义中就没有-1,0-1的结果是当前的位数最大值,比如如果是八位,那么0-1=255; 当然,好像我的编译器自动帮我修正了,所以我的显示是对的,但是思想就是这样,如果你不想以后找bug都没地方找的话,这些细节是要注意的!

3、 字面值常量
  • 字面值常量就是一个数值,这个数值的含义包括整形数,bool数,字符等,比如说 42,“String”,True,其表现形式多种多样,可以是long,short, 科学计数法,十进制,十六进制等等,字符和字符串字面值分别是两种,需要注意的是:字符串字面值以 “\0”表示结束,但是这个字面值字符不可见,所以其实所有的字符串字面值的长度都要比看得到的+1 比如 “HelloWorld!”就有12个字符长度。
  • 转义序列:就是很多常见的不可见但是需要的辅助字符:
  • 举个栗子,如果你在标准输出里面加入一个\a,那么你的程序执行的时候你会听到一个常见的警报声,留心观察哦
代码语言:javascript
复制
cout<<u1-u<<"\a"<<endl;
cout<<u-u1<<endl;

上面第一行就会输出一个警报声,虽然不可见,但是你可以听到,哇咔咔,这个是最出人意料的,我一直都不知道呢

4、 变量定义

  • 变量的初始化可以用已经定义的变量去初始化新的变量,请注意,初始化和赋值是完全不同的东西,初始化指的是创建这个变量的时候获得一个特定的值。而赋值的定义是把对象当前的值擦除,然后赋予新的值来替代原本的值。 默认初始化。默认初始化即定义的是如果变量定义的时候没有显式的初始化,那么它的值将由定义的位置决定。

  • 如果是定义于函数体外的变量会默认初始化为0,而函数体内的内置函数变量不被初始化,即未定义初始化值。
  • 当然,对于类,如果在类的定义中有初始化的值,就不需要函数体来操心了。定义一个类的对象的时候就会默认的代入这个类的默认初始值(如果不进行显式的初始化)
  • 建议是初始化每一个内置类型的函数,虽然并非强制,但是会比较安全。提高整体的可靠性,是一个优秀的习惯。
5、变量声明和定义
  • 变量的声明。声明是规定了变量的名字,类型,这一点与定义相同 变量的定义。规定了变量的名字,类型。并且还申请了存储空间,也可能赋予一个初始值。可以这么说,定义是建房子(包括定计划的全套,可能还会添置家具),声明就是定计划,并且只是定计划,取啥名,长啥样,至于在哪儿,怎么建,一概不管。
  • 如果声明一个变量而不是定义,那么加一个关键字extern 。
代码语言:javascript
复制
extern int j;   // 声明j而不是定义,还没有分配内存空间。
int l;   //定义l
//如果显式初始化j 那么等同于定义
extern int j=1;   //等同于int j ,定义。
  • 变量可以多次声明,但是只能定义一次。

  • 也许这两个差别看起来很不明显。但是如果我们要在多个文件中使用同一个变量,那么就必须将声明和定义分开,定义只能出现在一个文件中,其他用到该变量的文件必须对其进行声明,但是绝对不能重复定义。
6、 标识符
  • C++的标识符由字母,数字,下划线构成,并且标识符的开头只能是字母或者下划线而不能是数字。并且标识符对大小写敏感。
  • 书上有说两个要求,但是我实际跑的时候没报错,也许是我的自动更正了?还是说是新特性?如下(毫无压力):
    1. 不能连续出现两个下划线 ;
    1. 不能以 下划线紧接着大写字母开头;
    1. 函数体外的标识符不能以下划线开头。
7、 名字的作用域

作用域的概念其实就是,一个变量,跳不出定义这个名字的那个范围最大的花括号。在函数体外的就是全局作用域,一旦声明以后,全局作用域的变量就可以在整个程序内部通行使用,但是会存在地头蛇问题,如果在在局部作用域内定义了一个同名的变量,那么就会覆盖。但是一旦出了局部作用域,就会重新回到原来的全局变量。

代码语言:javascript
复制
#include <iostream>    
using namespace std;

int QuanJu=32;

int main()
{
int JuBu=100;
cout<<QuanJu<<endl;
cout<<JuBu<<endl;

int QuanJu=0;
cout<<QuanJu<<endl;

cout<<::QuanJu<<endl;

int CeShi=QuanJu;
cout<<CeShi<<endl;

return 0;
}

其实完全可以看做是那一块局部作用域被屏蔽了。全局变量作用不进去,局部作用域的操作对全局变量也没有一毛钱的影响!!下面是经典案例:

代码语言:javascript
复制
#include <iostream>

using namespace std;

int QuanJu=0;

int main()
{
int JuBu=100;
for (int JuBu = 0; JuBu != 10; ++JuBu)
{
QuanJu+=JuBu;
}
cout<<QuanJu<<" "<<JuBu<<endl;

return 0;
}

神奇不神奇?!!!全局变量纵横天下,哪里都去的,所以可以一直累加,但是当高层的作用域在内层的作用域内被重名的时候,就会造成强龙不低地头蛇的现象。当前,地头蛇也伤不到强龙就是了。所以JuBu这个变量除了for的作用域后没变化。

8、 复合类型之引用(引用和指针)
  • 引用就一种形式:(引用必须初始化,不然会报错。)
代码语言:javascript
复制
int ival=1024;
int &refVal = ival; //这里就是一个引用,从此refVal就绑定了ival,其实就相当于计算机网络中的域名和ip的关系。
int &refVal2 //在此处就会报错,具体参考域名无法解析到IP时候的痛苦你就懂了,既然是取别名,那么倒是给我整个人让我取别名啊。我对着空气说,这个人叫张三啊!!

请注意:引用并非是重新定义对象,而是给对象取别名,定义结束后,那就完成了引用与这个对象的绑定!以后对谁操作都无所谓了,反正二者都指向一片地址空间。就好比一个妹子张九嫁给了张三,就绑定了。那么不管张三以后改名了?被人打残了?找小三张五了(取另外的别名)了。只要你说张三变了。那么就是张九的男人变了。张三的别名就是张九的男人,也可以是张五的男人啊,张五的男人变了,张九的男人这个对象也就变了对不?反正就这么个意思。当然,引用的对象类型正确,定义一个int的引用,不能绑定一个char的对象。好比张九不能嫁给瘊子张三啊。我们不提倡跨越种族的爱恋!!

正文之后

迫于政治压力。特此关闭情感专题,有缘再见了各位!