C++ 变量也许和其余语言的变量没有什么差异.就是用来存储一些可能会变值的容器.
固然 C++ 变量里又分为 原子类型 的(int , char ,bool 等等),复合类型 的(struct ,class ,union).
这篇内容会比较侧重与于记录些原子类型的变量的使用和注意事项.其实我想不少都记录在原文中,可是无奈怕篇幅太长.并且让人生厌.因此给出了一些连接让有兴趣的同窗方便查看.html
咱们能够按照变量的实际保存数据的类型分割为一下几个类别 程序员
int
(4字节) short
(2字节) long
(在 32 位系统下是 4 字节,64 位系统则是 8 字节)float
(4字节) double
(8字节)char
(1字节) wchar_t
(这个在内存中的所占的大小,可能根据使用的 字符集 不一样而不一样,好比你在 VS 上用默认是 utf16le 那么它大体是占 2 个字节,gcc 上默认是 utf8 ,其宽度是 4 字节) bool
(1字节)函数指针
(例如 int (*pFunc) (void),这里定义了一个 pFunc 函数指针,指向返回值为 int ,参数列表为 void 的函数指针.这个是属于 c 范畴的内容啦.因此这里不详细介绍了有兴趣的能够点这个 连接(函数指针) 或这个 连接( C++ 成员函数指针) 参考看看.我在一开始时候学习到这个特性的时候,仍是很痛苦的.常常和返回值为指针的函数原型弄混) 指针变量
(用于记录某些变量地址)
这里简单的列举出来变量的定义形式(引用必须在声明时候显示赋值):数组
int i; // 定义整型变量 int *p; // p 为指向整型数据的指针变量 int a[n]; // 定义整型数组 a 有 n 个元素 int *p[n]; // 定义指针数组 p,有 n 个指向整型指针 int f(); // f 为返回整型函数值的函数 int *p(); // p 为返回一个指针的函数,该指针指向整型数据 int (*p)(); // p 为指向函数指针,该函数返回一个整型值 int **p; // p 为一个指针变量,它指向一个整型的指针变量 int &p = a; // p 为整形变量 a 的引用 int *& p2 = p; // p2 为整形变量指针 p 的引用(能够查看这里的例子)
那在实际的开发中在定义变量时候最好给变量显示赋予一个初始值.为何这么作呢,若你在定义变量的时候并未显示赋值,那么你的变量一开始里面保存的数据是不肯定的.好比定义一个整形 int a; 这句话仅仅只是为 a 这个变量分配了一个内存空间,而 a 的内容取决于你当前分配那块内存的值,那这个就是很不肯定的了.因此假设你不当心使用了一个为经初始话的变量,可能就会致使程序崩溃等等.数据结构
整形变量就是用来存放整数的地方.那么整数又是如何被存储在内存当中的呢?答案是以 补码 (这里是有关 [原码] ,[反码] ,[补码] 的相关说明,若想知道的更深刻能够 [点这里])的形式存放在内存中.若了解了这个的话,那么算术异常你也就大体知道是什么缘由了,为什么两个很大的数相加会获得一个负数.
还须要注意的是 C++ 对于 1000 0000 表示的数变不在是 0 而是 -128(即 -127-1).由于在有符号数中表示 -0 的这个数实际意义上是最小负数在减一. 固然实际是应为 -128 刚恰好对应的二进制补码为 1000 0000 除符号位外也.
在计算机当中其实它只识别二进制的形式,即 0101 这种的形式(由于没有什么电路的专业知识因此这里也很少作解释,以避免误导到你.个人理解是电路中存在两种状态即,有电,没电.对应的便是 1, 0).
由于计算机的整形存储是以二进制的形式.因此有个细节能够注意,对于整数进行 2 的次幂乘除的时候,能够用移位来实现.这样效率会更高函数
下面来扩展下思路.既然计算机存储的数据格式是二进制,那么咱们就简单下如何用布尔运算来实现有符号整数加法与乘法的方式.这里只是作个扩展思路,实际计算机的操做可能有被优化过.学习
-- 加法 --优化
一个加法能够拆分红布尔运算的 *与* 与 *异或* 的组合的屡次迭代 两个数相与后再左移 1 位能够获得这两个数相加的 *进位*, 而两个数的异或能够获得两个书相加的 *本位* 若 *进位* 为 0 那么,当前的 *本位* 及是加法的运算结果,若不为 0 重复将 *进位* 与 *本位* 继续进行 *与* 与 *异或* 直至 *进位* 为 0. 举个例子吧 第一轮: 本位: 101001 ^ 001001 = 100000 进位: 101001 & 001001 = 001001 << 1 = 010010 第二轮: 本位: 100000 ^ 010010 = 110010 进位: 100000 & 010010 = 000000(为 0 结束) 因此的到 101001 与 001001 的相加结果 110010
-- 乘法 --编码
乘法的本质就是加法的迭代,那么咱们能够用更贴近计算机处理的思路来想问题.若 n * m,能够讲 m * n 拆分红 m*(2^x + 2^y + 2^w + ...) 举个例子: 好比 6 * 5 , 而后我按照 m*(2^x + 2^y + 2^w + ...) 的拆分能够获得 6(2^2 + 2^0),那下面我就用二进制的表达式列出下运算公式. 110 * 101 = (110 << 000) + (110 << 010) = 110 + 11000 = 11110 这里看似正常,可是若 n,m 中出现了负数的话运算结果却会使人瞪目结舌.正像上面说的负数也是以补码形式存放在内存中的.那么咱们可能要在运算前对 m,n 进行一步处理,即把 m,n 还原成源码再而后在进行运算.固然在运算时候切记不要把符号位带入运算当中.并且得到运算结果后记得把结果转换为补码的形式.
既然了解了整形变量是如何存储在内存当中的,那么咱们也了解下浮点型是如何存储在内存中的吧.浮点型是遵守 [IEEE 754] 标准.也能够点 [这里] 简单地了解下什么是浮点数.也正由于它存储数据的方式.致使它所表达的具体值可能存在精度不够准确.指针
既然计算机只能识别些 1010 的二进制那么字符又是如何被存储的呢?固然你不可能 'a' 这个字符直接写入内存中,那么就找个折中办法吧.咱们用一个数值来对应一个字符.而后把这个记录在内存中,接着咱们就能够经过这个数值找个这个字符.下面咱们就简单的了解一些相关的专业名词和对于的解释吧.code
这里可能要补充一点 当你在使用 char 时候,若第一个字符大于 0x80,那么就必须检查下一个字节,才能判断一个完整的字符.
在使用变量的时候应该注意变量的生存周期(即变量的做用域),以避免引用了已经脱离做用域的变量,好比返回了一个指向函数局部变量的指针.可参看下表:
变量存储类别 函数内 函数外 做用域 存在性 做用域 存在性 auto 与 register √ √ × × static(局部) √ √ × √ static(外部) √ √ √(只限本文件) √ extern √ √ √ √
在初步了解变量的做用域,顺带这里也能够初略解下 C++ 在编译的程序时候会把程序内存分为的几个部分: