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

正文之前

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

正文

1、 算数类型

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

  • 整形又分为有符号的和无符号的,有符号的为默认,无符号的需要声明 unsigned。类型char表现于这两种的哪种取决于编译器的类型
  • 选用类型的几点建议:
  • 明确知晓不会小于0时,选择无符号数
  • 使用int时,如果超出了取值范围,那么用long long
  • 浮点运算的时候请选用double 因为float的精度通常不够!而且性能开销相差不大

2、 类型转换

  • 编译器可以自动的转换类型, 也有强行转换类型的:
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看做一个定长的类型,那么这个程序就是不可移植的!
  • 对无符号类型的表达式
    • 如果对一个无符号数赋值一个负数,那么计算机会对这个负数进行无符号数的解答。就好比上面的倒数第二句:
unsigned char c=-1;   // 假设char占8bits,那么c的值是255,而不是-1;
  • 如果char是8bit那么其无符号数的范围就是0 ~ 255,如果是有符号数,那么就是-128 ~ 127 所以上面对无符号数赋值负数,解读为正数就是255 而不是-1; 也许我们不会这么做,但是如果进行算术操作,计算机会自动的把有符号数转换为无符号数进行计算,已达到类型匹配的目的。所以不得不防!!
#include <iostream>    
using namespace std;

int QuanJu=32;

int main()
{

    unsigned u=10,u1=42;
    cout<<u1-u<<endl;
    cout<<u-u1<<endl;
    return 0;
}

结果如下:

  • 另外,你有时候可能会无意间造成死循环,比如下面的函数
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,那么你的程序执行的时候你会听到一个常见的警报声,留心观察哦
cout<<u1-u<<"\a"<<endl;
    cout<<u-u1<<endl;

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

4、 变量定义

  • 变量的初始化可以用已经定义的变量去初始化新的变量,请注意,初始化和赋值是完全不同的东西,初始化指的是创建这个变量的时候获得一个特定的值。而赋值的定义是把对象当前的值擦除,然后赋予新的值来替代原本的值。 默认初始化。默认初始化即定义的是如果变量定义的时候没有显式的初始化,那么它的值将由定义的位置决定。
  • 如果是定义于函数体外的变量会默认初始化为0,而函数体内的内置函数变量不被初始化,即未定义初始化值。
  • 当然,对于类,如果在类的定义中有初始化的值,就不需要函数体来操心了。定义一个类的对象的时候就会默认的代入这个类的默认初始值(如果不进行显式的初始化)
  • 建议是初始化每一个内置类型的函数,虽然并非强制,但是会比较安全。提高整体的可靠性,是一个优秀的习惯。

5、变量声明和定义

  • 变量的声明。声明是规定了变量的名字,类型,这一点与定义相同 变量的定义。规定了变量的名字,类型。并且还申请了存储空间,也可能赋予一个初始值。可以这么说,定义是建房子(包括定计划的全套,可能还会添置家具),声明就是定计划,并且只是定计划,取啥名,长啥样,至于在哪儿,怎么建,一概不管。
  • 如果声明一个变量而不是定义,那么加一个关键字extern 。
extern int j;   // 声明j而不是定义,还没有分配内存空间。
int l;   //定义l
//如果显式初始化j 那么等同于定义
extern int j=1;   //等同于int j ,定义。
  • 变量可以多次声明,但是只能定义一次。
  • 也许这两个差别看起来很不明显。但是如果我们要在多个文件中使用同一个变量,那么就必须将声明和定义分开,定义只能出现在一个文件中,其他用到该变量的文件必须对其进行声明,但是绝对不能重复定义。

6、 标识符

  • C++的标识符由字母,数字,下划线构成,并且标识符的开头只能是字母或者下划线而不能是数字。并且标识符对大小写敏感。
  • 书上有说两个要求,但是我实际跑的时候没报错,也许是我的自动更正了?还是说是新特性?如下(毫无压力):
    1. 不能连续出现两个下划线 ;
    1. 不能以 下划线紧接着大写字母开头;
    1. 函数体外的标识符不能以下划线开头。

7、 名字的作用域

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

#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;
}

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

#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、 复合类型之引用(引用和指针)

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

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

正文之后

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

原文发布于微信公众号 - 工科狗和生物喵(gh_3507b116a1f8)

原文发表时间:2017-11-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AzMark

Python学习之面向对象

1203
来自专栏fangyangcoder

leetcode(一)

问题描述看图1,大致意思是最初自己手上是没有任何钱,一杯柠檬水5刀,买家有三种给法(5,10,20),在给定的input,也就是money的序列,问你是否找的开...

1672
来自专栏java架构师

读【重构】读书笔记之一 代码的坏味道

一、重复的代码: 包含完全重复、部分重复、以及程序不同结果相同 1)一个类的两个函数有相同的表达式  ---提取方法 2)两个互为兄弟的子类含有相同表达式---...

2707
来自专栏HappenLee的技术杂谈

C++雾中风景9:emplace_back与可变长模板

emplace_back方法最大的改进就在与可以利用类本身的构造函数直接在内存之中构建对象,而不需要调用类的拷贝构造函数与移动构造函数。

882
来自专栏C/C++基础

STL四种智能指针

STL一共给我们提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr和weak_ptr,auto_ptr是C++98提供的解决方案,...

3713
来自专栏java学习

Java每日一练(2017/7/20)

最新通知 ●回复"每日一练"获取以前的题目! ●【新】Ajax知识点视频更新了!(回复【学习视频】获取下载链接) ●【新】HTML5知识点视频更新了!(回复【前...

2626
来自专栏机器学习从入门到成神

设计模式之静态工厂、工厂方法和抽象工厂的联系与区别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35512245/articl...

892
来自专栏数据结构与算法

1487 大批整数排序

个人博客:doubleq.win 1487 大批整数排序  时间限制: 3 s  空间限制: 16000 KB  题目等级 : 黄金 Gold 题解 题目描述 ...

2815
来自专栏小詹同学

Leetcode打卡 | No.017 电话号码的字母组合

欢迎和小詹一起定期刷leetcode,每周一和周五更新一题,每一题都吃透,欢迎一题多解,寻找最优解!这个记录帖哪怕只有一个读者,小詹也会坚持刷下去的!

1473
来自专栏Python小屋

Python编程一定要注意的那些“坑”(九):0与False

问题描述:在编程时,经常需要单独编写一个函数用来判断某个事件是否成立,如果成立就返回正常结果,否则返回False。在主调函数中根据被调函数的返回值决定下一步的操...

1283

扫码关注云+社区

领取腾讯云代金券