C++之数据类型与运算符

前言

最近在学习数据结构的时候发现C++里面的很多数据类型、运算符的常识在特殊情况下能起到奇效,所以我想对这些基础做一个小小的总结,以方便后续使用。

1.基础数据类型

对于数据类型,我们需要掌握的是有哪些数据类型每种数据类型在32位/64电脑上的内存占用如何其数值范围是多少,而这些都是一一相关的,数值范围自然只跟数据所占字节位数以及unsigned和signed有关:

数据类型说明32位字节数64位字节数取值范围16进制量级
bool布尔型11true,false--
char字符型11-128~1270x7F
unsigned char无符号字符型110~2550xFF
short短整型22-32768~327670x7FFF3万
unsigned short无符号短整型220~655350xFFFF6万
int整型44-2147483648~21474836470x7FFFFFFF21亿
unsigned int无符号整型440~42949672950xFFFFFFFF42亿
long长整型48---
unsigned long无符号长整型48---
long long长整型88---
float单精度浮点数44---
double双精度浮点数88---
*指针48---
ssize_t计数类型48---
size_t无符号计数类型48---

注:1字节byte=8位bit,1KB=1024B=2^13bit,1M=1024KB==2^23bit,1G=1024M=2^33bit

其中要特殊注意的地方有:

  • 受操作系统位数影响的数据类型只有long指针size_t等基础类型,都是从4字节变为8字节;

  • size_tssize_t等同于longunsigned long

  • 对于大数据处理,利用int的数值范围作为bit数组的索引,其中unsigned int的取值范围为0~2^32-1,所以存储一个42亿大小的bit数组需要用1/2G=512M内存;

  • char字符串数组的定义形式有:char a[] = {‘a’, ‘b’, ‘\0’},或者char a[] = “ab”;

  • 由于操作系统中编译器会进行内存对齐,其中32位/x86系统对齐内存为4字节,x64系统对齐内存为8字节,即内存地址是4的倍数,这就意味着,对于32位系统中的例子如下:

    1
    2
    3
    4
    5
    6
    7
    struct A{
    A(){}
    ~A(){}
    int m1;
    char m2;
    static char m3;
    }

    这个结构体占8字节内存,这是因为类的大小只与成员变量(非static成员)的虚函数指针有关,因此只需要考虑m1m2的内存占用,即4+1=5,但是由于内存对齐的作用,其会占用8字节。

  • 指针的内存占用与指向的内容无关,即double *并不是说指针类型为double;

  • float和double的取值范围计算方式很独特,比如float的4字节=32位,包括1符号位+8指数位+23尾数位,所以其取值范围为:
    $$ value = significand \times {2^{exponent}} $$
    由于指数位为8,所以指数范围为-127~128,那么其取值范围为-2^128~2^128,而尾数位23决定了其精度,即2^23 = 8388608,共7位,所以只能有7位有效数字,其中只能确保6位。

    同理double有1符号位+12指数位+53尾数位,保证15~16个有效数字。

2.Ascii码

ASCII 码使用指定的7 位或8 位二进制数组合来表示128 或256 种可能的字符,一般常用的字符只有128种。其中我们要特殊注意的有:

  • ascii码中的48~57对应十进制中的0~9;
  • ascii码中的65~90对应大写字母中的A~Z;
  • ascii码中的97~122对应小写字母中的a~z;

3.运算符

3.1算术运算符

1561457171613

其中要特殊注意的是有:

  • +*运算符可能造成数据内存溢出;

  • /默认返回int类型的结果;

  • ++--需要注意的是:

    1
    2
    i++ => y = i;i = i + 1;return y;
    ++i => i = i + 1; return i;

    相对来说,i++多了一个临时变量,另外它的过程是先引用在自增,一定要注意,一般来说自增操作会在最后执行,具体看后续的运算符优先级。

3.2关系运算符

1561457735075

3.3逻辑运算符

1561457789698

这里要注意的是在使用逻辑运算符时,一定要判断何时为true,何时为false,在c++中,以下情况会被认为false:0falseNULL\0nullptr

3.4位运算符

1561458372274

位运算符主要包括与(&)或(|)非(~)异或(^),之所以叫位运算,是因为其是针对2进制数进行操作的,我们利用位运算可以做很多便捷的事情:

  • 对于&,利用这个我们可以用来逐渐将一个数变为0,通过n&(n-1),每次执行都会将一个1的位置零,因此其有效执行次数就是这个数的2进制形式中的1的个数;
  • 奇偶性:a&1为0时候表示其为偶数,否则为奇数;
  • 取相反数:~a+1这个过程就是负数的2进制转换操作,先取反,然后+1;
  • 取第k位数:a>>k&1,其中k是从0开始计算的;
  • 每8位取出数,可用于图像:a>>24&0xFF,a>>16&0xFF,a>>8&0xFF,a&0xFF;
  • 判断正负:a>>31为0则正,否则为负。

3.5赋值运算符

1561459504434

3.6杂项运算符

1561459518315

这里面有几个要注意的点有:

  • sizeof返回的是数据的内存占用,单位为字节,而&返回的是数据的地址,*返回的是指针指向的数据内容;
  • ,运算符返回的是最后一条语句的值,eg:a=(1,2,3),返回3;
  • .->都可以被用来引用成员,但是->一般用于指针类型结构体/类;
  • cast并不是真正的运算符,其包括static_cast、dynamic_cast、reinterpret_cast和const_cast等方式,具体不描述。

3.7运算符优先级

1561460738997

运算符的优先级很重要,比如下面几个例子:

  • 1 << 3 + 2 & 7等价于 (1 << (3 + 2))&7
  • a++*2等价于y=a*2; a=a+1; return y
  • ++a*2等价于a=a+1; return a*2

参考资料

  1. https://www.runoob.com/cplusplus/cpp-operators.html
-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!