1、变量的初始化
C++11为我们提供了多种初始化方式
int n_a = 10;
int n_b(20);
int n_c = { 0 };
int n_d = {}; // 初始化为0
int n_f{};
花括号初始化器除了可以用在单值变量上,还可以用来初始化数组、结构体等:
int narr[] = { 1, 2, 3,4 ,5 };
struct Rect
{
int width;
int height;
};
Rect rect = { 10, 20 };
vector<int> vec = { 1, 2, 3, 4 };
vector<int> vec2{ 1, 2, 3, 4 };
2、无符号类型
假设int为32位,那么int(signed int)的范围是(-2147483648 ~ 2147483647),unsigned int的范围是(0 ~ 4294967295),当变量出现溢出的情况时,其值将为范围另一端的取值
int a = -2147483648;
cout << a - 1 << endl; // 2147483647
a = 2147483647;
cout << a + 1 << endl; // -2147483648
unsigned int b = 4294967295;
cout << b + 1 << endl; // 0
b = 0;
cout << b - 1 << endl; // 4294967295
3、常量类型
我们可以在数字后面加上'L'、'uL'来表示数字是long或者是unsigned long,以此类推'f'、'LL'等
auto a = 1000;
cout << sizeof(a) << endl; // 4
auto b = 1000LL;
cout << sizeof(b) << endl; // 8
4、char:字符和小整数
char c = 48;
printf("c = %d\n", c); // 48
printf("c = %c\n", c); // 0
c = 'b';
printf("c = %d\n", c); // 98
printf("c = %c\n", c); //b
c = '5';
printf("c = %d\n", c); // 53
printf("c = %c\n", c); // 5
我们通过%c打印出来的就是char字符本身,或者是数值对应的ASCII码值,常见的65对应'A',97对应'a',48对应'0'。
默认情况下,char既不是没有符号,也不是有符号,只是单纯的字符类型;我们可以显式的将类型设置为unsigned char 和signed char。unsigned char范围是0~255,signed char范围是-128~ 127。
5、const限定符
我们要尽量使用const限定符来替换#define,因为使用const可以指定类型,同时可以通过作用域规则限定在特定的文件或者函数中,另外const还支持更为复杂的类型,例如数组和结构。
6、浮点数
浮点类型有两种表示方法:小数点表示法和e表示法
float f = 13.34; // 小数点表示法
float f1 = 3.13e3; // e表示法
float f2 = 3e-3;
float f3 = 3e3;
printf("f1 = %f, f2 = %f, f3 = %f, f4 = %f\n", f, f1, f2, f3);
// f1 = 13.340000, f2 = 3130.000000, f3 = 0.003000, f4 = 3000.000000
printf("sizeof(float) = %d\n", sizeof(float)); // 4
printf("sizeof(double) = %d\n", sizeof(double)); // 8
浮点常量和整数常量类似,可以通过加一个后缀来表示:
1.24f // float
1.23E20F // float
1.23E28 // double
1.2L // long double
比较重要的一点:float的有效数字为6位,指的的float的数据只有前6位是精确的:以下例子中的fb的小数部分都是不精确的
float fa = 12.345677101231;
float fb = 123456.12312312414;
printf("fa = %f, fb = %f\n", fa, fb);
// fa = 12.345677, fb = 123456.125000
double的有效数字为15位。
7、C++运算符
运算符优先级:如果两个运算符被用于同一个操作数,则首先应用优先级高的运算符;如果两个运算符优先级相同,则根据结合性规则决定哪个运算符结合的更为紧密。
以下表格中同一组中运算符的优先级和结合性相同
运算符 | 结合性 | 含 义 | |
优先级第1组 | :: | 作用域解析运算符 | |
优先级第2组 | |||
(表达式) | 分组 | ||
() | L-R | 函数调用 | |
() | 值构造 | ||
[] | 数组下标 | ||
-> | 间接成员运算符 | ||
. | 直接成员运算符 | ||
const_cat | 专用类型转换 | ||
dynamic_cast | |||
static_cast | |||
reinterpret_cast | |||
typeid | 类型标识 | ||
++ | 加1运算符(后缀) | ||
-- | 减1运算符(后缀) | ||
优先级第3组 | (都是一元运算符) | ||
! | R-L | 逻辑非 | |
~ | 为非 | ||
+ | 正号 | ||
- | 负号 | ||
++ | 加1运算符(前缀) | ||
-- | 减1运算符(前缀) | ||
& | 地址 | ||
* | 解除引用 | ||
() | 类型转换 | ||
sizeof | 长度 | ||
new | 动态分配内存 | ||
new [] | 动态分配数组 | ||
delete | 动态释放内存 | ||
delete [] | 动态释放数组 | ||
优先级第4组 | |||
.* | L-R | 成员解除引用 | |
->* | 间接成员解除引用 | ||
优先级第5组 | (都是二元运算符) | ||
* | 乘 | ||
/ | 除 | ||
^ | 取余 | ||
优先级第6组 | |||
+ | L-R | 加 | |
- | 减 | ||
优先级第7组 | |||
<< | L-R | 左移 | |
>> | 右移 | ||
优先级第8组 | |||
< | L-R | 小于 | |
<= | 小于等于 | ||
> | 大于 | ||
>= | 大于等于 | ||
优先级第9组 | |||
== | L-R | 等于 | |
!= | 不等于 | ||
优先级第10组 | & | L-R | |
优先级第11组 | ^ | ||
优先级第12组 | | | ||
优先级第13组 | && | 逻辑AND | |
优先级第14组 | || | 逻辑OR |
常见的例子:
const char *s = "abcd";
char c = *s++;
cout << c << endl; // a
char c1 = *++s;
cout << c1 << endl; // c
除法运算符的行为取决于操作数的类型,如果操作数都是整数则C++执行整数除法,结果的小数部分将被丢弃;如果其中一个操作数是浮点数,则小数部分将保留。
float f = 10 / 3;
cout << f << endl; // 3
f = 10 / 3.0;
cout << f << endl; // 3.33333
8、类型转换
C++在以下三种情况下可能发生数据类型的转换:
a.将一种算术类型的值赋给另一种算数类型变量时,C++将对值进行转换;
C++11在使用列表初始化时对类型转换比较严格,不允许缩窄,即不允许变量的类型可能无法表示赋给它的值
const int code = 66;
int x = 66;
char c1{ 123123 }; // not allow
char c2 = { 66 };
char c3 = { code }; // code为常量
char c4 = { x }; // not allow
x = 31231;
char c5 = x;
b.表达式中包含不同的类型时,C++将对值进行转换;
在计算表达式时,C++将bool、char、unsigned char、signed char和short转换为int,这被称为整形提升。
将不同类型进行算数运算时也会有转换,较小的类型将被转换为较大的类型。转换可以按照以下顺序来进行转换:
1 | 如果一个操作数是long double,则另一个也转为long double |
2 | 否则,如果有一个数是double,则另一个也转为double |
3 | 否则,如果有一个数是float,则另一个也转为float |
4 | 否则,所有的数都是整形,整形提升 |
5 | 这种情况下,如果两个数都是signed/unsigned,转换为级别高的类型 |
6 | 如果一个数有符号,一个无符号,无符号级别高于有符号,将有符号数转为无符号数所属类型(unsigned long + singed int) |
7 | 否则,如果有符号数可以表示无符号类型的所有可能取值,将无符号数转为有符号数所属类型(signed long + unsinged int) |
8 | 否则将两个操作数都转为有符号类型的无符号版本 |
c.将参数传给函数时,C++将对值进行转换;
取消原型对参数传递的控制时,传递参数将对char/short应用整形提升,float将提升为double。
强制类型转换:
int na1 = (int)12.232;
int na2 = int(12.231); // C++风格强制类型转换
printf("na1 = %d, na2 = %d\n", na1, na2);
static_cast<typeName>(value)