先导
- “单个的位只能表示有/无的概念,把位组合在一起,加上解释,即给不同的可能位模式赋予含义,就能够表示任何有限集合的元素”
位模式:0/1字符串,其中每个数位具有权重 - “计算机表示法是用有限数量的位来对一个数字编码,当结果太大以至于不能表示时,某些运算就会溢出(overflow)”
- “整数的运算满足整数算律,虽然可能溢出但是结果都相同”
(500*400)*(300*200) = ((500*400)*300)*200
“对于浮点数,由于表示精度有限,浮点运算不可结合”
(3.14 + 1e20) - 1e20 = 0.0 小的数精度被“吃掉”
3.14 + (1e20 - 1e20) = 3.14 括号计算结果0.0与3.14精度相近
2.1
- “机器级程序将存储器视为一个非常大的字节数组,称为虚拟存储器。每个字节由一个唯一数字标识,称为它的地址。所有可能地址的集合称为地址空间。这个地址空间只是一个展现给机器级程序的概念性映像。实际的实现是讲RAM、磁盘、特殊硬件和操作系统软件结合起来,为程序提供一个看上去统一的字节数组”
- “C编译器将每个指针和类型信息联系起来,这样就可以根据指针值得类型,生成不同的机器级代码来访问存储在指针所指向位置的值”
指针:值为某个对象的存储地址,类型为该对象的类型 “每台计算机都有一个字长(word),指明整数和指针数据的标称大小。虚拟地址是以这样的字长来编码,字长也就决定了虚拟地址空间的大小”
指针类型 T* 在32位机中为4Byte,64位机中为8Byte,因为指针必须能够存储所有的地址值int b = 2; int* a = &b; printf("%d\n",*a); //指针指向的内容,输出2 printf("%x\n",a); //指针的内容,b的地址,输出5fbff7ec printf("%x\n",&a); //指针的地址,a的地址,输出5fbff7e0 printf("%x\n\n",&b); //取b的地址,输出5fbff7ec unsigned char *c = (unsigned char*)&a; //c指向一个字节序列,指向指针变量a for(int i=0; i<sizeof(int*); i++){ printf(" %2.x",c[i]); //取出c指向地址的内容,即a存储的b的地址,输出 ec f7 bf 5f ff 7f ,该机器为小端(small endian)存储,即低地址存储低字节,即为5f bf f7 ec }
- “计算机系统的一个基本概念就是从机器的角度看问题,程序仅仅是字节序列,机器没有关于初始源程序的任何信息”
同一段程序的在不同机器上的机器代码不同,编码规则不同,二进制代码是无法移植的 - “掩码运算时一个位模式,表示从一个字中选出的位的集合”
0xFF表示一个字的低位字节,~0将生成一个全1的掩码且平台无关 - “逻辑运算符返回1/0,当参数为非0时返回true,为0时返回false”
- “如果逻辑运算符对第一个参数求值就能确定表达式的结果,就不会对第二个参数求值”
a && 5/a 不会造成0作除数
p && *p 不会引用空指针 - “逻辑右移左补0,算术左移左补符号位”
- “四则运算优先级比移位运算高”
二分中,这样写将导致语义错误,int mid = start + (end - start) >> 1;