C++ 记事本: 变量

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 字节)
    [还有在使用 wchar_t , char 类型时候须要注意区分要使用与之对应的容器或函数.好比 char 对应的字符串容器是 string,而 wchar_t 对应的容器是 wstring,而在屏幕输出上 char 对应的 cout,而 wchar_t 对于的是用 wcout]
  • 布尔类型
    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

  • 字符(Character)是指人类语言中最小的表义符号.例如 'A'、'B' 等;想知道更多点 [这里]
  • 字符编码(Encoding) 是指给定一系列字符,对应每一个字符赋予一个特殊的数值,并能够用这数值来表明对应的字符.例如,咱们给字符 'A' 赋予数值 0,给字符 'B' 赋予数值 1,则 0 就是字符 'A' 的编码;想知道更多点 [这里] 一帮咱们使用比较多的编码集是 ASCII , Unicode(utf-8,utf-16), GBK.
  • 字符集(Character Set) 是指给定一系列字符并赋予对应的编码后,全部这些字符和编码对组成的集合就.例如,给定字符列表为{'A','B'}时,{'A' => 0, 'B' => 1}就是一个字符集;
  • 字符序(Collation) 是指在同一字符集内字符之间的比较规则;肯定字符序后,才能在一个字符集上定义什么是等价的字符,以及字符之间的大小关系;每一个字符序惟一对应一种字符集,但一个字符集能够对应多种字符序,其中有一个是默认字符序(Default Collation);

这里可能要补充一点 当你在使用 char 时候,若第一个字符大于 0x80,那么就必须检查下一个字节,才能判断一个完整的字符.

 

-- 变量做用域 --

在使用变量的时候应该注意变量的生存周期(即变量的做用域),以避免引用了已经脱离做用域的变量,好比返回了一个指向函数局部变量的指针.可参看下表:

变量存储类别       函数内                 函数外
                 做用域    存在性        做用域      存在性
auto 与 register  √        √           ×           ×
static(局部)     √        √           ×           √
static(外部)     √        √           √(只限本文件) √
extern            √        √           √           √

在初步了解变量的做用域,顺带这里也能够初略解下 C++ 在编译的程序时候会把程序内存分为的几个部分:

  • 栈区: 由编译器自动分配释放的,存放着函数的参数值,局部变量的值,其操做方式相似于数据结构中的栈(申请)速度快,但程序员没法控制.
  • 堆区: 由程序员分配释放,程序员不释放程序结束时可能回收,分配方式相似链表(申请速度慢,易产生内存碎片).
  • 全局区/静态区: 全局变量与静态变量的存储是放一块的,初始化全局变量在一块区域内,未初始化的静态变量在相邻的另外一块区域内,程序结束后由系统释放,内存在整个运行期间都存在.
  • 字符常量区: 常量字符串就是放在这里,程序结束后由系统释放.
  • 程序代码区: 存放函数体的二进制代码,在这里存放的变量又称字面常量
相关文章
相关标签/搜索