c++数据类型基础

本文主要是总结一下C++语言常用的数据类型基础知识,如类型转换,整形的最大最小数值等。

无符号数

示例1

1
2
3
4
unsigned int u = 0xFFFFFFFF;
cout<<"u="<<u<<endl; //4294967295
u -= 31;
cout<<"u="<<u<<endl;//4294967264

无符号数0xFFFFFFFF是32位无符号数中的最大值。

示例2:无符号数和有符号数运算

1
2
3
4
5
unsigned int u = 10;
int i = -42;
cout<<"u="<<u<<endl; // 10
cout<<"unsigned(i)="<<unsigned(i)<<endl;//4294967296 + (-42)
cout<<"(i+u) ="<<(i+u)<<endl; // 4294967264

无符号数u和有符号数i相加前,把有符号数i转换为无符号数,结果等于两个无符号数相加。

示例3:

1
2
3
4
5
unsigned int u = 10;
int i = -1;
cout<<"u="<<u<<endl; //10
cout<<"unsigned(i)="<<unsigned(i)<<endl;//4294967295
cout<<"(i+u) ="<<(i+u)<<endl;//(4294967295 + 10) % (4294967296),其中4294967296是2的32次方

两个无符号数相加结果超出它表示范围时,先对这个超出表示范围的结果进行取模(对2的n次方进行取模),则得到了真正的结果。

示例4:无符号数都是整数。若给无符号赋值一个负数,则将该负数+2n得到最后的结果。

1
2
3
4
5
6
unsigned int x = 0xFFFFFFFF;
unsigned int u = 10;
unsigned int v = 42;
cout<<"x:"<<x<<endl;
cout<<"(v - u):"<<(v - u)<<endl; // 32
cout<<"(u - v):"<<(u - v)<<endl; // 4294967264: (-32 + 4294967296) % 4294967296的结果

示例5:当表达式中既有带符号数又有无符号数时,当带符号数值为负数时会出现异常情况,这是因为带符号数会自动转换成无符号数。

1
2
3
unsigned int x = 1;
int y = -1;
cout<<"x * y="<<(x * y)<<endl; //4294967295,y转换为无符号数(-1 + 4294967296) = 4294967295

常用的一些16进制数

  • 0xffffffff

0xffffffff是一个十六进制数。把它转换成2进制为:1111111..11(32个1)
把它转成10进制无符号数是:0xffffffff = 16x10^7+ 16x10^6+….+16x10^1+16x10^0 = 4294967295
把它转成10进制带符号整数为:
111111111111111(32个1表示的补码形式)转化为源码形式为10…00001(中间30个0),即-1。

1
2
3
4
unsigned int a = 0xffffffff;
cout<<"a="<<a<<endl; // 4294967295
int b = 0xffffffff;
cout<<"b="<<b<<endl; // b = -1
  • 0x3f3f3f3f

    0x3f3f3f3f用于表示无穷大.它具有诸多优良性质.
    无穷大 + 无穷大 = 无穷大
    无穷大 + 常数 = 无穷大

异或运算

异或运算满足交换律与结合律。
C = A ^ B (^是异或运算符),则 A = B ^ C, B = A ^ C

例1. A = 1011, B = 0101 , C= 1110
若A和B在某一位上都是1, 则C在该位上为0,则A或B的该位与C的该位相与就是1;若A和B在某一位上都是0, 则C在该位上为0,则A或B的该位与C的该位相与就是0。
若A在某一位为1, B在该位为0, 则C在该位上为1,则A的该位与C的该位相与就是0,B的该位与C的该位相与就是1。同理,A在该位为0,B在该位为1时可证成立。

按位取反~

1
2
3
4
5
6
7
int a = -2147483648;
cout<<"a="<<a<<endl; // -2147483648
cout<<" ~a="<<~a<<endl; // 2147483647
bitset<32> b1(a);
bitset<32> b2(~a);
cout<<"a: "<<b1.to_string()<<endl;// 10..00
cout<<" ~a: "<<b2.to_string()<<endl;// 011..11

补码、原码、求补运算

负数的补码由其原码对除符号位外各位取反末位加1,同样,由补码求原码也是对补码除符号位外,各位取反末位加1。
求补运算:不考虑符号位,对原码各位取反,并在末位加1。对一个数进行求补运算得到的是其相反数的补码。
如对0111进行求补运算,0111的真值为7。其补数为1001(补码),补码1001对应的源码为1111,真值为-7。

n &(~n+1)

这个表达式常用来取n中最右侧的1。这是因为, ~n是对进行按位取反。
例如:n = 1000,n=0111, ~n+1 = 1000, n & (n+1)=1000,只有n中最右边为1的位置为1。
n = 1010, n=0101,n+1=0110, n & (~n+1)=0010。

参考文献

[1] 0x3f3f3f3f: https://blog.csdn.net/hzh_0000/article/details/9468377