1--该章节新知识点
① 类型转换
unsigned char c = -1;
printf("%d\n", c);
假设 char 类型占 8 比特,则 c 的值为 255,具体原理如下:
step1:-1 在内存中的存储形式为:
原码:10000000 00000000 00000000 00000001
反码:11111111 11111111 11111111 11111110 (负数:符号位不变,按位取反)
补码:11111111 11111111 11111111 11111111 (负数:反码 + 1)
step2:赋值给变量 c,需要阶段补码的低字节数据,即 11111111
step3:由于变量c是无符号,最高位仍为数据位,所以使用 %d 打印时需要进行整形提升,即: 补码: 00000000 00000000 00000000 11111111;
step4:正数的原码、反码和补码相同,打印原码时仍为:
00000000 00000000 00000000 11111111,即 255;
#include <iostream>
int main(){
unsigned u = 10;
int i = -42;
std::cout << u + i << std::endl;
return 0;
}
假设 int 占 32 位,则输出为 4294967264,具体分析如下:
step1:执行 u + i,需要将 i = -42 转换为无符号数,-42 的三码如下:
原码:10000000 00000000 00000000 00101010
反码:11111111 11111111 11111111 11010101
补码:11111111 11111111 11111111 11010110
step2:-42 转换为无符号数后,最高位为数据位,而 u = 10的三码相同,10 的补码如下:
补码:00000000 00000000 00000000 00001010
step3: -42 和 10的补码相加,结果如下:
补码:11111111 11111111 11111111 1110 0000,对应的数据为 4294967264;
② 字符串和字符的一个区别:
字符串字面值的类型实际上是由常量字符构成的数组;
每个字符串的结尾处会添加一个空字符,即 '\0';则字符串字面值的实际长度会比内容多 1;
字面值 'A' 表示单个字符 A,而字符串 "A" 则表示一个字符的数组。该数组包含两个字符,就 字符 'A' 和 空字符 '\0';
③ 内置类型的变量未被显式初始化时,其值由定义的位置决定:
定义于任何函数体之外的变量会被初始化为 0,而定义在函数体内部的内置类型变量将不会被初始化;
④ 变量声明和定义:
使用 extern 关键字来声明变量:
extern int i; // 声明 i
int j; // 定义 j
extern double pi = 3.14; // 定义(extern 语句包含初始值就属于定义,不属于声明)
变量能且只能被定义一次,但可以被多次声明;
⑤ 空指针 和 void*指针:
生成空指针的方法如下:
int *p1 = nullptr;
int *p2 = 0;
int *p3 = NULL;
nullptr 是一种特殊类型的字面值,其可以被转换成任意的指针类型;
void* 是一种特殊的指针类型,其一般用于与其它指针进行比较、作为函数的输入或输出、赋值给另外一个 void* 指针:
void *pv = &obj;
// obj 可以是任意类型的对象
⑥ 复合类型的声明
变量的定义包括一个基本数据类型和一组声明符;
在一条定义语句中,基本数据类型只有一个,但声明符的形式可以不同,即:
int i = 1024, *p = &i, &r = i;
// i 是一个 int 型的数,p 是一个 int 型的指针,r 是一个 int 型引用;
int* p1, p2; // p1是指向 int 的指针,p2 是 int;
// 一般建议写成 int *p1, p2,避免产生误导;
未完待续!