给初学者的编程指导

2023-06-05 0 1,033

写作时数约 10 两分钟,期望对你有协助。

介绍到许多爸爸妈妈想“音频文件”来同时实现在欧美国家领到护照,即使欧美国家两极化开发人员资金缺口非常大。 但许多非计算机系的同学,会真的程式设计“极难进阶”,不认知为何会这种,要那般。 这首诗,并非有关具体内容程式设计,而要主要就阐述确切程式设计是甚么,和先期的自学方向。

从三个范例已经开始

我对个人雷西县,假如最终目标是严肃认真的将程式设计做为几项能度日的组织工作,能 C 词汇做为算数词汇。 即使这能让你更介绍程式设计的技术细节因此能免遭自学繁杂的句法。假如修完 C 词汇,提议可自学 Lisp 词汇做为补足,这种能对绝大多数当代词汇都具有Monestier的潜能。

#include <stdio.h> int main() { int a = 5; int b = 10; int b = a; int c = a + b; printf(“a + b is: %d\n, c); return 0; }

下面是三个单纯的 C 词汇范例,用以把三个位数加起来,并把答案告诉你。

相信你初次看到这段代码,会有以下疑问:

为何我需要写一段这种的东西 ?为何计算机不能直接告诉我想的答案呢 ?为何写程序不能像平时说话一样呢 ?那般的话,我就不用自学这种一堆乱七八糟的东西了第一行的 #include 是啥意思,为啥我还没有要表达我的逻辑,就要先写三个和我逻辑没啥关系的东西 ?为啥每行后面都加三个分号,有甚么意义吗?这里的 a 是类似于数学上的变量嘛 ?a = 5, b = 10, 那为何 a 还能等于 b ?这是在侮辱我的数学老师 :)int 是啥意思 ?main 是干嘛的,我能起三个其他的名字吗 ?printf 是打印的意思嘛?但我只有显示器,我需要买三个打印机才能来学程式设计课嘛 ?为何最后一行还要写 return 0 ?我已经完成我的事情了啊,都输出结果了

或许,你的老师会告诉你,这个 C 词汇就是这个样子的,就像你学英语,你就需要自学英语句法对不对 ? 但其实呢,在计算机的世界里,所有的事情,大部分都是有原因的。就像是为啥造CPU时,为啥把用的材料叫晶圆而并非晶方呢。为啥整数的编码大端和小端会争这么多年呢?

文章的后面,就下面的这些问题,笔者尝试给出解释,注意部分解释有主观成分。

为何我需要写一段这种的东西 ?为何计算机不能直接告诉我想的答案呢 ?

单纯来说,是计算机硬件本身提供的潜能,实在是太弱了。弱到甚么程度呢 ? 只有下面几种单纯潜能:

你能: 在纸上记录三个位数你能: 在纸上擦除三个位数你能: 将纸上三个位数相加,并写到纸上你能: 假如把下面的几个事情,称之为指令,那你还能把“一串指令”按顺序写到纸上,我们把这一串指令称为程序你能: 可以按照顺序执行一串指令(也就是程序)你能: 能根据纸上三个位置的位数,打破一串指令执行的顺序,跳转到另三个位置已经开始执行

请注意下面这段内容的重要性。把上文的 “纸”,替换为内存,把 “你” 替换为 “CPU”,就像当代最常用的计算机顶层结构: “冯·诺依曼结构”。

注意,这是常用,并非唯一。就像你下班回家(10KM),常常会乘坐汽车。但,理论上,还有其他非常多的方式,例如步行、骑车、倒立行走、从高楼跳伞滑翔等等。选择这种方式,是早期探索了各种建造计算机的方式后,发现这种单纯省事。为何单纯省事,那肯定也是有原因的,但我不想在这里展开,这种你可能读不完这个新手指引。

你假如非要看看 CPU 设计图纸长啥样,简化亿点点后,就类似下面这种(但我提议你现在不用纠结,早晚会懂的):

给初学者的编程指导

我们回到原来的问题,“为何计算机不能直接告诉我想的答案呢 ?”

那是即使造计算机的科学家们不够努力啊,造了三个无比单纯且机械的机器,就把先期的组织工作交到开发人员手里了啊。不过,这也有三个好处,硬件成本比较低。 就像现在的工厂车间为啥不全搞人工智能呐?那是即使适当的人工,能节省一大笔钱。 计算机也是这种的,目前的硬件是半成品,要完成后面的功能,需要亿点点人工的成分,这部分人工就催生了现在开发人员这个职业~ 假如哪天计算机底层能更智能,而人工成本高到不如让整个事情自动化,那就会让开发人员这个职业消失。

现在,将要做开发人员的你,应该能认知,你要面对的计算机硬件,是三个无比单纯,需要靠你的双手让它完成更多事情。

为何写程序不能像平时说话一样呢 ?那般的话,我就不用自学这种一堆乱七八糟的东西了

其实,下面的解释,已经部分解释了这个问题。计算机真的很傻啊,能做的事情就那么几件,做个加减乘除之类的,当给你一台计算机,怕是你都想象不出来,构成现场生活的重要底层设施,竟然如此单纯。

所以,我们要用另外一种,非常机械的方式,来和计算机做个互动,辅导一下它的组织工作。

例如,我们想算一下,三个数的和是多少。

首先,你需要把三个数写到纸上然后,要把另三个数也写到纸上然后,告诉 CPU 把这三个数加起来,写回到纸上

在这时,你可能会有一些疑问,纸这么大,我该怎么告诉 CPU,那纸上哪三个数加起来了。

平常你是怎么定位书上的某个字呢 ?是并非类似于 “第5行的第4个字”。 哎,这并非巧了,内存也是这种的。 还发明了三个术语: 地址(Address)来指代内存上的某个位置。 这个位置的表达方式,从物理的角度看呢,表达为三个 (X,Y) 坐标更合理一些(假如是二维的话)。只是我们的计算机科学家们,还是有一些用户体验意识的,把内存认为宽度是固定的,就让我们用三个数就能表达地址了,内存会自动把地址转换为内部的 (X,Y) 坐标。

这里我解释了一下内存地址的概念,内存非常大,我们想在内存里面存放一点东西的话,就需要三个地址,来告诉 CPU 你想存到哪里,内存地址的形式呢,是三个整数,这只是三个方便的记法,实际上,会有硬件将表达内存地址的整数翻译为真实存储的物理上的地址。

所以,总结一下,你真的不能对计算机硬件要求太高,它自身能做的东西真的非常单纯。

第一行的 #include 是啥意思,为啥我还没有要表达我的逻辑,就要先写三个和我逻辑没啥关系的东西 ?

哎,这就是三个非常关键的问题了。

我们下面说了,计算机硬件真的非常单纯啊,老板让你写个程序,“预测一下明年公司的营收会增长多少 ?”。但这可不愁坏你了,这老板的需求,和在纸上做加减乘除差别有点大啊,“老板,请给我和在纸上做加减乘除相关的任务,谢谢”,“好的,明天去财务领工资”。

俗话说,做大事还是需要站在巨人的肩膀上。一些常见的功能,已经有人帮我们同时实现了,一般称这些公用的模块,称之为库(library)。库有许多,所以要按需引用。 而我们刚已经开始写的这个 #include <stdio.h> 就是要使用 stdio 这个标准库。

但,你可能有个问题,之前我们讲到计算机硬件只有少数几个功能,似乎不包括这个引用库的功能。那这个引用要如何生效呢 ?

这就要引入 “程式设计词汇” 的概念了。程式设计词汇是这种一种东西,它让你不必直接与硬件打交道,程式设计词汇为你提供了一层逻辑抽象,程式设计词汇为你提供了一份烹饪说明书,你只要按照程式设计词汇给你提供的句法,就能更高效完成组织工作。

常见的程式设计词汇包括下面这些,我分了一些类别,具体内容的分类依据,相信后面你会认知的 🙂

C、C++、Python、Java、Golang、JavaScript 等等Lisp、Haskell、Erlang 等Shell、AWK 等SQL 等

但,编程词汇给你提供便利特性的同时,也并非免费的。程式设计词汇需要做为中间人,将你写的源码,转译为机器能认知的极为单纯的那几种操作。假如是程序运行之前就完成转译,就称为编译型词汇(如C、Golang),假如在执行时才完成转译,就称为解释型词汇(如Java、Python),但为了性能考虑,许多解释型词汇,也会一定的编译优化。

你可能会有疑问: 所有复杂的事情,真的都能用那几种机器直接支持的单纯的操作完成嘛 ? 我的回答是: 并非所有的复杂事情都能(有一些事情是永远无法完成的),但绝绝大多数你遇到的问题都能,这就是所谓的大道至简吧。

标准库 一般是程式设计词汇自带提供给你的基础潜能。越成熟的词汇,标准库就越为强大。 而假如你自己写了一段能分享的代码,也能做为第三方库,被别人引用。

不同词汇引用库的方式有差别,C/C++ 用 include,Python/Java/Golang 用 import。

为啥每行后面都加三个分号,有甚么意义吗 ?

其实在 C 词汇,分号和我们英语/汉语中的句号很像。就是表达这个语句我写完了,已经开始下三个。 这个分号你若非要问为啥要加,这还真的是程式设计词汇作者的对个人偏好。 像是 JavaScript 就加不加分号都行,而 Golang 则是不推荐加,虽然你加句法也能通过编译。

假如说分号到底有啥优势,有这种三个语句分隔符,能降低编译器做句法解析的难度及降低句法二义性的概率。 但我相信这个问题并非非常重要,单纯的认知这是程式设计词汇作者自己的审美观念就好。

这里的 a 是类似于数学上的变量嘛 ?

程式设计词汇通常将 a 这种能存储数值的标识符,称为变量,和数学上的变量语义相近,其他确实能变的。 但程式设计词汇一般也会提供常量这种定义,顾名思义,就是不能改变值的东西。

我对个人真的,变量和常量概念是从数学中迁移过来,语义近似。

但你可能会有疑问: 我为啥要起个名字 a, b 呢,这背后的逻辑是啥 ?

我们先想象一下,假如不写 a 这种变量的名字,你要如何表达你的程序,可能是下面这种:

#include <stdio.h> int main() { int $189808900 = 5; int $619880001 = 10; int $619880001 = $189808900; int $890902782 = $18980890 + $619880001; printf(“a + b is: %d\n, $890902782); return 0; }

我们新发明了三个句法,$189808900 指内存中地址为 189808900 的区域。 这下好了,我们没有变量的命名了,随之而来的是谜一样的地址魔法。这还是几行程序,假如面对上万行的代码,相信眼睛要瞎掉。

期望通过这个范例,能说明为何需要做三个变量的命名。

编译器/解释器 会负责将变量名映射到正确的物理位置 很遗憾,在真实世界,这里有额外复杂性,这个地址不一定指内存(但绝大多数情况是),还可能指的是I/O设备,CPU 寄存器

a = 5, b = 10, 那为何 a 还能等于 b ?这是在侮辱我的数学老师 🙂

绝大多数程式设计词汇的 = 都并非数学上的表达式两边等价的意义,而要指右边的值,需要赋值到左边。就是说,这类似于物理上的复制,但并非移动。

a = b 是指将地址为 b 空间中的值,复制到 a 对应的地址对应的空间中。注意 b 的值并非被移动过去,而 b 变为空的,b 还是会是原来的值。

数学上的比较大小的 =,在 C 词汇中对应的是 ==。不同的词汇,有不同的句法表达方式。

int 是啥意思 ?

int 称为数据类型声明,表达这个数据的类型为整数。 你可能又有疑问了,“我为何需要数据类型?我并不需要数据类型 :)”

其实,这个问题很单纯,例如你想把三个位数,写到纸的三个地方,不同大小的位数,占的纸版面大小不一样。但你能后面会修改这个数对吧?这时,你可能要为是否要为这个位数预留一点版面来方便后面修改困扰。因此,程序设计者将决定这个位数占多大版面的任务交到了你手上,比较只有你自己这个位数后面还要不要改,会不会要占用更多版面空间。

int 代表你想让这个数占用 4 个字节的版面空间。4个字节是 32 位,能表达 [-2^31, 2^31-1] 的数值区间。 具体内容技术细节,需要自己探究了,这里版面也很有限~

main 是干嘛的,我能起三个其他的名字吗 ?

main 你能认知为,你写了三个程序,想交给硬件去执行,但编译器需要知道应该从哪里已经开始执行,这个 main 就是三个小小的提示,告诉编译器,需要从 main 这里已经开始执行。

但通常情况下,这个入口你必须按程式设计词汇约定的来,你写其他名字,程式设计词汇可能不认。我为啥只是说可能呢,即使其实我也没有太大把握,在不同的操作系统和编译器版本,可能会有一些例外发生。

那为啥不能从第一行能执行的代码已经开始执行呢 ?这种不就不需要 main 了 ? 你要非要这种问,那我真的还真的能这么做。前提是所有代码需要都写在三个文件,因此,前面的 main 也能引用后面定义的一些函数之类的。 但若要这么搞,感觉还是没有 main 定义来的灵活。

printf 是打印的意思嘛?但我只有显示器,我需要买三个打印机才能来学程式设计课嘛 ?

printf 表达需要将内容输出出来,写 print 只是一种历史习惯,在显示器没有发明之前,是将输出到纸片上的。

在当代的家用计算机上,执行 printf 一般都是输出到屏幕上,所以并非需要买三个打印机 ~

为何最后一行还要写 return 0 ?我已经完成我的事情了啊,都输出结果了

这个不同词汇习惯不一样,在 C 词汇里面,程序在退出时,需要返回三个位数,称为 Exit Code。用以程序结束时,调用程序的人能知道程序是否正常执行完了。

按照 C 词汇的约定习惯,正常结束通常返回 0,有错误时返回其他位数。

后面你会发现这个 Exit Code 还是有一些用的。例如在内存不足时,许多程序会返回 137 退出码,这种你就能知道程序是即使内存不足,今儿为排查故障提供了一些依据。

先期自学规划提议

编程本身是一件相对来说比较单纯的事情,但不单纯的地方在于程式设计词汇之外。

第一阶段: 程式设计词汇进阶 (大约 3 个月)

程式设计词汇为你提供了三个舒适、密闭的词汇环境,但只有跳出这个舒适的环境,你才能真正认知计算机世界和写出更好的程序。

自学方向,我推荐从 《C 程序设计词汇》Brian W. Kernighan & Dennis M. Ritchie 已经开始,一遍不行两遍三遍。 注意程式设计本身是三个偏实践的事情,认知基础的句法后,一定要用到真实的场景中。

自修完 C 词汇,提议自学下面的一种或者几种词汇,有利于就业,看自己的兴趣方向:

Golang, 云原生、后台开发方向Java、Scala,后台开发、大数据方向C++,数据库、游戏、音视频、嵌入式方向 (注意 C++ 有许多特性,只需要自学核心子集就能了)Python,数据分析、机器自学、测试、运维方向SQL,基础技能,提议每对个人都会,注意 SQL 是一种思维方式和沟通工具Bash Shell,后台开发、运维基础技能JS、HTML、CSS,Web 开发全家桶Android/iOS 应用开发Julia、Rust、Lisp、Haskell、Lua 在国内短期可能不好找组织工作,但可学一下扩展视野PHP、Ruby、Perl 不提议学了

第二阶段: 增强基础专业素养 (大约 2 年)

算法数据结构计算机体系结构网络存储分布式操作系统

这个阶段,推荐 CMU 的系列公开课,和参与开源项目。 注意自学公开课时,重要要看一下课程列的参考材料,从参考材料里面再找参考材料,形成系统化的知识结构。

第三阶段: 细分领域深入研究 (不限)

进一步加强数学基础机器自学数据库大数据安全软硬结合型研究顶会发 Paper

这个阶段我也还没有突破,给不了太多提议,一起加油吧 ~

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务