Bits Bytes and Integer
1.1 Information is Bits in Context
比特(binary digit),是表示信息的最小单位,状态0和1。
源程序是一个由0和1组成的位序列(也称为比特序列),8个位被组织为1组,称为字节。每个字节代表程序中的某些文本字符。大部分现代计算机使用ASCII标准来表示文本字符,用单字节整数值来区分每个字符。只有ASCII字符组成的文件称为文本文件,所有其他类型的文件称为二进制文件。
为了在系统上运行hello.c程序,每一条C语句必须被其他程序翻译成低级机器语言指令的集合,这些指令按照称为可执行目标程序的格式打包好,作为二进制磁盘文件存储。
在Unix系统,源文件到目标文件的转换需要编译驱动程序。
gcc -o hello hello.c
ls
hello hello.c
Centos 安装gcc编译器 yum -y install gcc gcc-c++ kernel-devel //安装gcc、c++编译器以及内核文件
GCC编译器驱动程序将源文件hello.c翻译成可执行目标文件hello。翻译过程的执行需要4个阶段,预处理、编译、汇编、链接。执行4阶段的程序pre-processor预处理器,compiler编译器,assembler汇编器,linker链接器构成了编译系统。
计算机系统和硬件组成
所有应用程序对硬件的尝试必须经过操作系统。
操作系统有两个主要功能:
- 保护硬件不会被失控的应用程序滥用
- 向应用程序提供简单一致的机制来控制不同低级的硬件设备
通过基本的抽象概念实现:进程、虚拟内存、文件。
进程
进程是计算中的程序关于某数据集合上的一次运行活动,是系统资源分配和调度的基本单位。
shell进程通过“系统调用”将控制权传递给操作系统,操作系统保存shell进程的上下文,创建一个新的hello进程的上下文然后将控制权传递给hello进程,待hello进程执行完毕操作系统恢复shell进程的上下文和传递回控制权。
线程
一个进程由多个可执行单元组成,称为线程,每个线程运行在进程的上下文中,共享同样的代码和全局数据。多线程成为越来越重要的程序模型,多线程比多进程更容易共享数据,因为线程比进程一般来说更高效。
虚拟内存
虚拟内存是一个抽象概念,为每个进程提供一个假象–每个进程独占使用主存。每个进程看到相同的内存,称为虚拟地址空间。
字
机器字长:机器字长是指计算机进行一次整数运算所能处理的二进制数据的位数。觉得虚拟地址空间的大小,n位比特的机器字长,虚拟地址的范围是0-2n-1,程序最多能访问2n个字节。
字节顺序有两种方式:大端模式和小端模式。假设int类型变量x=0x01234567在机器中有两种存储方式。
大端模式:是指数据的高字节保存在内存的低地址中。
小端模式:是指数据的高字节保存在内存的高地址中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PFV9p45H-1589163218916)(Bits Bytes and Integer.assets/截屏2020-05-09 下午10.09.22.png)]
大多数intel兼容机都只采用小段模式。
C语言移位运算
右移运算有两种形式:逻辑右移和算术右移。
逻辑右移左端补k个0,算术右移左端补k个最高有效位的值。
无符号数与有符号数
二进制转无符号数,UMin = 0, UMax = 2w-1
二进制转有符号数,TMin = -2w-1,TMax = 2w-1-1
有符号与无符号比较时,会隐式地将有符号转成无符号数进行运算。
#include <stdio.h>
int x = -1;
unsigned int y = 0;
if (x > y) {
printf("x > y");
} else if (x == y) {
printf("x = y");
} else {
printf("x < y");
}
}
output:
x > y
此时-1与0u比较,需要将-1转换为有符号数比较,假设int是64机器上4字节,-1的有符号表示是4294967295,所以-1>0u。
有符号与无符号数有很多陷进,极大刷新了我的认知。
#include <stdio.h>
int main() {
unsigned int i;
for (i = 10; i >= 0; --i) {
printf("hello world\n");
}
}
#include <stdio.h>
int main() {
int i;
for (i = 10; i - sizeof(char) >= 0; --i) {
printf("hello world\n");
}
}