当歌吧 关注:644贴子:2,313
  • 3回复贴,共1

学会了 C 语言真的可以开发出很多东西吗?

只看楼主收藏回复

马里奥碰到花朵就变身。
什么是马里奥?一个装着 16 × 32 个小色块的长方形,其中一些色块填着颜色,另一些没有。什么是花?一个 16 × 16 的正方形。什么是「变身」?把马里奥这个方块里面代表衣服的褐色变成红色,代表背带裤的红色变成白色。什么是褐色?暂且说它是 0x887000 这个数字。什么是「碰到」?马里奥的长方形与花朵的正方形有所重叠。什么是「重叠」?假设马里奥的这个方块占据屏幕(什么是屏幕?一个能装下 256 × 240 个小色块的矩形)中 X 方向 101 到 116、Y 方向 21 到 52 之间的区域,那么只要这个区域内有一点或更多点也被花朵所占据(比如花朵处在 X 116 到 131、Y 21 到 36 之间的区域内),我们就认为两者有所重叠。
若给定以八个数值代表的两个矩形区域,请写出判断两个区域是否有重叠的 C 语言程序。如果你能写出来,那么祝贺你,如果有朝一日你想自己做一遍 NES 版本的《超级马里奥》,你至少知道让他变身需要做什么了。
是的,C 语言也许「只能」做数学题。可是,绝大多数游戏的运行过程就是不停地做数学题,而所谓编写游戏,也就是把游戏的规则和游戏的效果转化为数学题而已。其中不少题目电脑都已经知道怎么解——是别的程序员事先告诉它的——比如「求一堆散落在三维直角座标系之中的多面体体在 8(x−3)−10(y+1)−11(z−1)=0 这个平面上一个给定范围内的投影」或者「给定一些彼此相连的顶点,求任意两点之间的最短路径」之类的数学题,它只需要千万分之一秒就能给你解好。这种能力有什么用?电脑上 FPS 游戏的本质活动就是不停地求三维座标系下的多面体经过变换之后在二维平面上的投影,不停地判断两个多面体是否彼此重叠,以及不停地寻找两个顶点之间的最短路径,最终达到让怪物冲到你面前咬你一口的目的。不止游戏如此,其他软件也都差不多,每一个细节都是某种数学题——比如知乎页面顶端的蓝色导航条背景,就是 CSS 描述的一个浅蓝到深蓝的渐变——渐变是怎么回事呢?给出两个数字分别代表两种颜色,以及第三个数字代表一段距离,求一系列颜色的数值以及次序,使得这段距离中两种相邻颜色之间的变化最小。数学题。别说 C 语言,一切编程语言最终都只能做数学题,根据给定的数据,算出另一些数据,算出更多的数据,然后存贮、发送或者呈现算出的数据。
不过我能理解你的困惑。投入大量时间看完教程,结果只能在黑框里输出一串数字。这是在学编程还是在向七十年代致敬?编程是这样无法给人成就感的活动吗?是,也不是。看你的表述,应该不是小孩子了,因为小孩子不会因为初学编程能做的事情很少而没有成就感,或者说,觉得这样做没有成就感的小孩子根本不会继续学下去。最初学编程的成就感单纯来自于「我居然可以指挥机器做一些事」,至少我小时候用中华学习机编一个程序帮我算暑假作业上的四则运算题时是这样感觉的。写这些程序并用它解题的时间虽然远超过自己动笔去把题目算出来,却让人乐此不疲。那时候我还不知道马里奥碰到花会变身这种事情其实也是靠编程编出来,所以我也不会去想学编程「并不能做什么」。
无奈大多数人过了一定年纪就很难再靠「我能指挥机器」这种简单原始的快乐来驱动自己学编程。见过世面,听过传言,欲望和野心变得复杂而庞大,你想要图形界面,音乐音效,人工智能,云端同步,可是你闷头学了几堂课,还是只学会在黑框里显示一串数字。你怀疑这是学 C 语言的错,于是你到知乎上来问了这个问题。
你的疑惑是有道理的。
如果能把编程学下去,日后你就会明白,任何程序都是一座冰山,最终用户能看到的界面和使用的功能,只是程序浮在水面上的十分之一。知乎这个网站其实也是个运行在某台电脑上的程序,你能看到的十分之一是用什么编写的呢?HTML,CSS,JavaScript,或者 Objective-C。而你看不到的那十分之九是用什么编写的呢?Python。这些你无法直接观测到的 Python 程序运行在世界某个角落的某些计算机上,隔着光缆、双绞线和无线基站,为你面前或掌上的用户界面注入生命。
http://xkcd.com/353/
……可是 Python 是用什么编写的呢?C 语言(当然,这么说并不严谨,Python 理论上可以用任何其他语言实现,实际上也已经被用很多其他语言实现了,不过这并不是重点)。任何编程语言都是实现某个功能的工具,Python 实现了知乎这个网站的大部分功能,而 C 实现了「用 Python 写程序」这个功能。为什么是 C?
C 很别扭又缺陷重重,却异常成功。固然有历史的巧合推波助澜,可也的确是因为它能满足对于这样一种系统实现语言的需要:既有相当的效率来取代汇编语言,且又足够地抽象而流畅,能够用于描述各种各样的环境之下的算法与交互。
C is quirky, flawed, and an enormous success. Although accidents of history surely helped, it evidently satisfied a need for a system implementation language efficient enough to displace assembly language, yet sufficiently abstract and fluent to describe algorithms and interactions in a wide variety of environments.
——C 语言之父,Dennis M. Ritchie
C 是初代程序员所使用的语言,那时候硬件很贵,软件必须高效;而计算机的用户都是职业程序员,对于硬件有足够的理解。C 贴近硬件,就意味着它容易译成机器能懂的语言,而它的设计者也并不需要操心普通人学起来可能会比较困难——而且,说真的,其实也不很难。但是,这么多年过去之后,软件规模变得越来越大,C 就像锤子和手锯,修小木屋得心应手,造摩天楼就比较力不从心;但 C 语言可以用来造出其他更适合建造摩天楼的工具,乃至组成摩天楼的预制件,就好比用锤子和手锯造出挖掘机和吊车、混凝土板和一体门窗一样(当然,这个类比并不十分贴切。可是没有什么类比能贴切地描述软件工程,因为软件工程像许多东西,却又什么东西都不像)。
所以,回到你的问题上来,是的,学会 C 计算机语言真的可以开发出很多东西,但除非内力深厚,场合适当,并且闲得蛋疼,大多数人不会拿 C 或者只拿 C 来开发太大的东西。如果你只是想要一门能够让你「编辑出一个啥子游戏或者软件出来」的语言,而且你用 Windows,那建议你转去学学 C#。它长得和 C 挺像,但却能迅速地写出至少是带有图形界面的程序,用起来也很方便,鼠标点一点就能让你对自己的程序看起来什么样有个比较直观的印象。还有,在国内,C# 的教材也相当容易找到。当然 Python 也是一个很好的选择。

另外,还有一件事你必须弄明白:现代的所谓编程这一活动,其实大部分时候是在「合理地堆砌别人已经实现的功能来实现新的功能」,C 语言莫不如是,比如 printf 这个东西,是别人做出来的「把一些数据按照指定格式输出到屏幕上」这一功能。而别人还做出来许多其他功能,比如「在发现用户短时间内连续两次按下鼠标又松开的时候调用你写好的一个函数」。学会怎样在 C 或者其他任何程序语言中使用这些既有功能,也是学习编程的一门重头戏。等你弄明白这一点,你也就找到了你问题的答案。


IP属地:上海1楼2014-06-14 17:08回复
    何煁
    JU huang、哟嚯、JAYUS 等人赞同
    什么是计算机?一个加法器(仅会1+1)和一个搬运工。这就是我认为的计算机。
    那为什么世界可以这么美?
    减法用补码加,乘法多次算,除法转乘法。这是计算。
    8位一字节,128个ASCII码,数字就成了字母。
    字母组单词单词做指令,数可以代表指令也可以代表运算部件,指令有操作码和操作数。指挥加法器操作数。这时候是汇编。
    图像RGB三元色256灰度,声音44.1kHz采样,汉字两字节unicode。于是世间音形变成01。
    有了这些,我便可以用单片机控制led。我传1你就亮,这是开关。当我128*64个液晶一起控制,这是12864液晶显示屏。当我1920*1080这就是锤子的屏幕。于是显示器出来了。怎么现实锤子二字?怎么使用键盘扫描a这个字母?怎么打开wifi模块?怎么写驱动?这都是c语言在干的。这就是驱动。
    驱动出来了,处理器改怎么分配时间,内存怎么占用,硬盘内存cache怎么分,进程何时用,外设驱动怎么处理,等等,这些写好了就是简易操作系统吧。linux内核全用c哦,这就是操作系统。
    屏幕可以任意显示了,音响可以随意响了,有os做底层支撑了。然后我让屏幕显示一把枪,我定义它为一个物体,定义一些操作,比如扣动扳机。再定义一些人物,场景,定义一些规则。这就是cs了吧。这里枪只是一个枪,我不会去管它怎么画怎么显,我只要知道他是一个东西,我可以用它。这就是面向对象编程。
    于是就出来了楼主所说的游戏。当然游戏还牵扯到gpu等外设,还牵扯到建模,曾见过物理博士就搞游戏里水怎么建模,流体嘛,什么美工,什么渲染,联网还要数据库,外挂还有脚本
    但是从那三极管的电子空穴阴阳中和到你一枪爆头有关系吗?
    让你学c不是让你用它写出什么中国版linux,是为了让你明白如何去操作工具。学的是如何用机器思想思考。而不是你说开机就开机。
    入门,学的是语法的抽象。是知道名词动词和句子有结构这个事实。至于汉语主谓宾和英语主谓宾,学了一个另一个不就好懂了吗
    我也不知道我要说啥了T T。
    这里的每一段的一个功能或许就是几百个博士教授一生的目的。
    其实就是讲计算机的一些原理。对象语言更多的是使用工具,比如库,函数,调用什么的。而c是他们的基石。
    更新于22夜晚
    我们大家都忘了一个事,软件真的只是写代码吗?写代码只占了不到百分之十吧,大多的是在维护,规划,文档,找bug。。。。
    编程语言有好多,
    汇编,是最直接效率最高,但是看到一堆1001谁都眼花。别信什么传说曾经有人用针在光盘上刻出过一个操作系统,现在几乎都可以用c代替了吧。但是还要懂一点灵魂。
    c是高级结构语言,但还是偏向与硬件。linux仅仅几百k的源码大多就是什么处理器内存存储管理,进程管理。linux牛是因为他驱动多。c就是一线员工,危险都得上,但少了他不行。老师们教导我们劳动只有分工不同没有贵贱之分。反而很多c工程师待遇超好。
    java ,cpp,c sharp,是对象语言。像是将军指挥下属,不必去知道盔甲怎么铸造。
    javascript之类脚本语言,这个没学,不太懂,不敢说了,求介绍
    matlab fortan之类偏向数学吧。什么控制,图像处理,识别,人工智能,神经网络,机器学习。感觉好高大上哦。这些东西都是你看不到,但神奇的可以很实用的问题,这就是数学的魅力。你知道一个傅里叶变换搞出了多少高科技吗???看系里有人学这个好羡慕,自己没那命。
    vhdl, verilog hdl之类的。纯硬件语言。这个不是通用cpu,是cpld,fpga之类的大量运算,这种语言弄得是芯片里的布线,就是改变硬件连接。而通用cpu那些只是重复。这个里面就有了ip核,很有用的知识产权。什么arm架构,其实卖的不是芯片,仅仅是芯片规划也就是ip核,中国这个可怜啊,这才是赚钱的地方呢。以前听过一个老师说,你以为我们愿意买美国国债啊,你不买,ip核不卖你,你就不行。哎,intel,arm什么这个积累多啊,中国,哎不说了。希望华为海思可以搞好吧。
    html之类,求指教
    但所有编程不都是一个理嘛,一个物质操纵另一个物质,加法器操作数,系统操作开关,屏幕。你的鼠标操纵一个对象,whdl操纵一条电子线路。
    当然还差很多,要实现这些,还有太多太多。
    最后什么国产e语言。我觉得没啥用,除了汉语好看,没一点用


    IP属地:上海2楼2014-06-14 17:09
    回复
      赵紫川,夫唯弗居 是以不去
      林永、敖腾渊、季业 等人赞同
      可以,数学就是编程的全部。
      至于为何数学是编程的全部,我就引用一下我之前给一个人答疑解惑时的邮件的部分内容,我在这里直接贴出来好了:
      ======================分割线========================
      编程是什么。
      这是个大问题。
      随着时间的变化,计算机工作者在做的事一直在变化,从使用机器码在纸带上打孔到用打字机输入汇编指令,到用命令式的语言写下更接近自然语言的代码,到行业分化,出现了算法设计,架构优化,网络工程,系统工程,前后端分工,协议接口设计,移动开发,等等,几乎每一代计算机工作者都以不同的方式使用或陪伴着计算机。
      不,编程不是对着屏幕敲键盘,不是精通什么什么语言,不是熟练运用VisualStudio/Xcode或者vim/emacs这类软件。
      这些都是和编程相关的形式和表象。
      编程存在于计算机诞生之前。
      早在牛顿写下《自然哲学的数学原理》的时候,早在笛卡尔发现了直角坐标系的时候,早在中国古人发明算盘的时候,编程就已经深深存在于人类文明之中了。
      这要慢慢来解释。
      我们中学的时候学到过物质守恒,能量守恒,后来我们又学到物质和能量可以互相转换,但是转化的过程中总有些东西是守恒的。守恒的是什么?
      中学的时候我们学到用x,y,z三个数字可以表示出一个三维坐标点的位置,后来我们学到三维点也可以用长度、角度、高度(柱面坐标)表示,也可以由长度,xoy平面角和yoz平面角(球面坐标)表示。但无论用哪种方式来表示,都要至少三个数字,而二维点无论在直角坐标系、极坐标系、复平面上,都需要两个数字来描述。守恒的是什么?
      最终一切守恒的是信息。
      这里的信息可以理解为完整定义一个事物所需要的数学单元(当然这不是关于信息正规的精确定义)。
      如果我们说两个点是等价的,我们就是指他们的信息等价。而至于这个点的信息究竟被表达为直角坐标还是球面坐标,对于这两点是否等价来说,无关紧要。
      就像一个点的信息可以被表达到多种坐标系下,我们可以一个事物全部/一部分的信息从一个表达形式转移到另一个表达形式上。
      这样的将信息表达到一个表达形式上的过程,或者将信息从一个表达形式上转移到另外一个表达形式上的过程,我们一般称为编码。
      而从表达形式上还原信息本来面目,或者从某种表达形式上把信息转移到另一种更加易于理解/使用的表达形式上,叫做解码。
      这样就诞生了编程的第一大要素——编程之“编”字即是编码。
      算盘,将自然数上所携带的一部分信息转移到算珠的表达形式上,就将这些自然数的一部分进行了编码。
      如果我们将一个水杯的一部分信息(比如形状——空间点的坐标集合或者带有手柄信息的贝塞尔采样曲面)存储在了某个载体里面,那我们就模拟出了这个水杯。(我手边正好有个杯子我就随手举例子了 > <)
      而如果我们能够将这个水杯的所有信息(所有的所有,包括每个原子,每个电子,每个夸克的相关数据)存储起来,那么这个完整的水杯就真实的存在于这个载体之中了,无论这个载体是我们的物理空间,还是一本厚厚的书,还是计算机磁盘,这个水杯只是以不同的编码存在于这三个不同的地方而已。
      我们知道了信息,就掌握了一切的开始。
      接下来我们需要的是一组规则。
      我们有了炮弹的发射初速度,质量,外形,所在大气的密度分布,角度等信息,为了算出落点,我们需要的是重力公式。
      这就是规则,旧信息在特定规则下产生新的信息,周而复始,我们就有了这个物体在整条时间线上的全部信息。
      事实上,这些规则本身也是信息,如果我们能够超越时间之外,就能看到规则实质上是在时间维度上完全压缩过后的信息,而时间本身就是对这一信息的解码产生的信息。
      如万有引力公式F=GM1M2/r^2,就是对万有引力这种规则所包含的信息的另一种编码形式,这种编码形式我们叫做程,方程的程,编程的程。
      这就是编程,设定一组规则和一些信息,然后让信息在规则下不断产生新信息,最终得出结果。
      信息在规则下产生信息,规则在信息下也可以产生规则。
      比如电脑游戏,就是一组规则(游戏规则)和一些不完整的初始信息(比如每个人初始有多少战斗力,每个装备卖多少钱),然后这些初始信息和规则共同作用,成为新的规则,新的规则等待用户输入的信息(比如鼠标的位置),然后产生新的信息(比如屏幕上显示的图形——像素分布)。ps. 关于规则接受不完整的信息产生新的规则,这个叫Currying,如果有兴趣可以查阅相关文献。
      这就是编程的本质,所以一些学有所成的程序员会说编程包含整个宇宙——如果你在计算机中创建了某个事物的一部分,那么你就在做一次模拟,如果你在计算机中编码了某个事物和相关规则的全部,你就在计算机里实实在在地拥有了这个事物——从数学上存在就是真正意义上的存在。(你可以创建足够强大的计算机来克隆整个宇宙,不过根据信息守恒你的计算机的信息量——比如质能总和——会比宇宙自身包含的更大,而且根据混沌原理你不能将这个计算机架设在你要克隆的宇宙中——信息守恒也解释了为什么任何算法都有一个不能逾越的时间复杂度)。
      计算机,不过是因为天生善于处理信息,而成为了编程的最佳载体——毕竟在屏幕上模拟行星运动比星象仪准确而且低成本的多。
      ===============================分割线==========================
      所以事实上编程就是数学,界面上显示那些花花绿绿的图像图形,不过就是一系列点的位置与颜色的数学表达,被解码在了屏幕上而已。


      IP属地:上海3楼2014-06-14 17:09
      回复
        摘自知乎www.zhihu.com/question/23844552
        虽然大家都在说知乎装B犯太多 但我觉得 在某个领域的入门阶段 知乎里的大牛们还是能一针见血的。


        IP属地:上海4楼2014-06-14 17:11
        回复