细说:程序运行的环境和运行过程,再看不懂请自行面壁

本文深入探讨程序运行的环境,包括CPU的寄存器和高速缓存,以及内存的管理。讲解了程序如何与操作系统交互,如虚拟内存的使用和栈帧的工作原理,帮助理解程序从编译到运行的完整过程。

本文已收录GitHub,更有互联网大厂面试真题,面试攻略,高效学习资料等

编译器的任务,是要生成能够在计算机上运行的代码,但要生成代码,我们必须对程序的运行环境和运行机制有比较透彻的了解。

你要知道,大型的、复杂一点儿的系统,比如像淘宝一样的电商系统、搜索引擎系统等等,都存在一些技术任务,是需要你深入了解底层机制才能解决的。比如淘宝的基础技术团队就曾经贡献过,Java 虚拟机即时编译功能中的一个补丁。

这反映出掌握底层技术能力的重要性,所以,如果你想进阶成为这个层次的工程师,不能只学学上层的语法,而是要把计算机语言从上层的语法到底层的运行机制都了解透彻。

文本我会对计算机程序如何运行,做一个解密,话题分成两个部分:

  1. 了解程序运行的环境,包括 CPU、内存和操作系统,探知它们跟程序到底有什么关系。
  2. 了解程序运行的过程。比如,一个程序是怎么跑起来的,代码是怎样执行和跳转的,又是如何管理内存的。

首先,我们先来了解一下程序运行的环境。

程序运行的环境

程序运行的过程中,主要是跟两个硬件(CPU 和内存)以及一个软件(操作系统)打交道。

本质上,我们的程序只关心 CPU 和内存这两个硬件。你可能说:“不对啊,计算机还有其他硬件,比如显示器和硬盘啊。”但对我们的程序来说,操作这些硬件,也只是执行某些特定的驱动代码,跟执行其他代码并没有什么差异。

1. 关注CPU和内存

CPU 的内部有很多组成部分,对于本文来说,我们重点关注的是寄存器以及高速缓存,它们跟程序的执行机制和优化密切相关。

寄存器是 CPU 指令在进行计算的时候,临时数据存储的地方。CPU 指令一般都会用到寄存器,比如,典型的一个加法计算(c=a+b)的过程是这样的:

  • 指令 1(mov):从内取 a 的值放到寄存器中;
  • 指令 2(add):再把内存中 b 的值取出来与这个寄存器中的值相加,仍然保存在寄存器中;
  • 指令 3(mov):最后再把寄存器中的数据写回内存中 c 的地址。

寄存器的速度也很快,所以能用寄存器就别用内存。尽量充分利用寄存器,是编译器做优化的内容之一。

而高速缓存可以弥补 CPU 的处理速度和内存访问速度之间的差距。所以,我们的指令在内存读一个数据的时候,它不是老老实实地只读进当前指令所需要的数据,而是把跟这个数据相邻的一组数据都读进高速缓存了。这就相当于外卖小哥送餐的时候,不会为每一单来回跑一趟,而是一次取一批,如果这一批外卖恰好都是同一个写字

### 计算正整数位数的方法 可以利用数学对数函数来计算正整数的位数。对于一个正整数 $N$,其位数等于 $\lfloor\log_{10}(N)\rfloor + 1$。这是因为 $\log_{10}(10)=1$,闭区间 $[1 - 9]$ 即为 1 位整数;$\log_{10}(100)=2$,闭区间 $[10 - 99]$ 即为 2 位整数,依此类推。在代码实现中,由于 `log10` 函数返回类型是 `double`,所以需要使用 `(int)` 进行强制转换。以下是 C 语言代码示例: ```c #include <stdio.h> #include <math.h> int figure(int num) { if (num == 0) { return 1; } else { return ((int)log10(num)) + 1; } } ``` ### 计算正整数各位数字之的方法 可以使用循环或递归的方式来计算正整数各位数字之。 #### 循环方式 通过不断地对数字取余得到最后一位数字,然后将其累加到总中,再将数字除以 10 去掉最后一位数字,直到数字变为 0。以下是 C 语言代码示例: ```c #include <stdio.h> int sumOfDigits(int num) { int sum = 0; while (num > 0) { sum += num % 10; num /= 10; } return sum; } ``` #### 递归方式 递归的基本思想是将问题分解为更小的子问题。对于一个正整数 $N$,其各位数字之等于最后一位数字加上剩余数字的各位数字之。当数字只剩一位时,递归结束。以下是 C 语言代码示例: ```c #include <stdio.h> int DigitSum(int n) { if (n / 10 == 0) { return n; } else { return n % 10 + DigitSum(n / 10); } } ``` ### 完整的 C 语言代码示例 ```c #include <stdio.h> #include <math.h> int figure(int num) { if (num == 0) { return 1; } else { return ((int)log10(num)) + 1; } } int sumOfDigits(int num) { int sum = 0; while (num > 0) { sum += num % 10; num /= 10; } return sum; } int main() { int N; printf("输入一个不超过 10^9 的正整数:"); scanf("%d", &N); int digitCount = figure(N); int digitSum = sumOfDigits(N); printf("%d %d\n", digitCount, digitSum); return 0; } ``` ### Python 实现 ```python N = int(input()) digit_count = len(str(N)) digit_sum = sum(int(i) for i in str(N)) print(digit_count, digit_sum) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值