不错,是个程序员料子。
没错,C的确比诸如C++、Java、python之类语言简单。
因为它什么都没有:32个关键字9种控制语句,然后是加减乘除与或非之类直接从数学里借来的若干运算符。没了。
简洁明了,自解释性强,正交度高,一个个概念搞清楚了,那真是做什么都简单。
相比之下,其他语言往往会引入更多的概念;这些概念往往还做不到“正交”,关系复杂,规则层出不穷;经常还极不直观……
对于跟着课本/教材亦步亦趋的初学者来说,当然是概念简单清晰、逻辑关系直白、在达成基本数据结构/算法这个目标上不带任何逻辑包袱的C更简单,更容易入门。
请注意我加粗的“跟着课本/教材亦步亦趋的初学者”这个限定。
一旦脱离了这个限定,第一段的讨论就成了无的放矢了。
这是因为,一旦你真的需要写点什么实用的东西出来,你就不得不面对“现实的复杂性”。
比如说吧,最简单的,见过电脑的bios界面吗?如果让你用C写个类似的东西呢?
类似的,如果让你写个视频解码器音频播放器呢?
你立刻就会发现,你必须面对如下问题:
1、你必须懂硬件原理(显示器原理、显存/屏幕空间的映射关系、硬盘存储寻道原理、音频采样/插值原理等等;以及CPU寄存器、流水线、cache、总线、锁等等等等)。
2、你不得不使用第三方库——比如,为了写一个bios式的界面,最省事的办法是用ncurses库。
3、其他语言直接提供给你的东西,你将不得不全部重新实现一遍——更加的笨拙,更加的不正交——粗糙的完全无法使用。
C要求,这1、2、3三点你必须全能。
它的库往往更原始,缺乏抽象,经常需要你根据自己的实际情况随手补全;
它要求你对硬件了如指掌:每条指令下去,从CPU标志位到内存到总线到显卡声卡,所造成的一切直接间接后果,你必须如数家珍、并把程序执行时每个实体的每个瞬间都安排的明明白白——哪怕状态变化的时序出现问题,那都是无法接受的严重bug;
最后,你需要自己就能够为python之类语言实现/改良它的字典,这才可能在C里面造一个不能被编辑器/编译器直接支持的类似物、然后还要把它用到自己的项目里。
相比之下,其他语言不需要你了解1,它甚至禁止你过于了解硬件,从而避免你被硬件的复杂性所影响;
它们有丰富完善好用的2,它们的库从一开始就是针对傻瓜用户设计的,用错了它甚至能给你提示;
你只需学会它们的3的用法、并不需要自己懂这些“神秘语言元素”的实现:你压根不需要像用C时一样,自己绞尽脑汁用最少的指令实现这类语言提供的基本设施——越是基本的设施越是值得字斟句酌:用python你可以直接用“字典”;但如果玩C,你得知道“字典”就是C里面你要自己实现的“哈希表”;而且并不是课本上的“玩具代码”,而是实实在在工业强度的、最优化的、支持一切key-value类型的、高度泛化的哈希表。
可见,哪怕你对C对数据结构有那么一丁点最粗浅的了解,你都绝不会用“python有字典”来证明它的难、证明C的易用——恰恰相反,学C的目标之一,正是为python实现字典、实现“无需区分变量类型的变量”、帮助初学者“不知道指针照样能用内存,因为我在后台偷偷替他们做了嘿嘿哈哈……”
换句话说,题主完全不知道想用好C需要什么。
你所罗列的、其他语言“难”的那些方面,恰恰证明了你对用好C需要哪些基础知识一无所知。
照着书拿把扳手拧俩螺丝便以为“儿得矣”,弄辆车让你拧方向盘挂个档你都摇头怕怕……可是,你要知道,C的设计目标,可是用来设计、制造汽车的哦。
做不到随时随地手撸一个变速箱出来,怎么能叫“懂C”呢。
“简单”这个词在汉语里可以代表两个维度上的含义:难度和复杂度。而 C 语言恰恰在这两个维度上处于两个反向极端。
如果说难度,那 C 语言确实很简单。
就那二三十个关键字,基本上已经少到减无可减的地步了。如果非要再精简的话,也就auto/signed/const等少数几个了。
而且在概念上,绝大部分和 cs 基本结构、形态也存在非常强的关联对应。如果你在这方面的基本功不错的话,你学 C 就会感到非常舒适,甚至会觉得理当如此。
有了上面两条,再加上语言本身的限制极少,所以逻辑能力比较强的人,简单的上手不就,就很容易折腾出各种花式玩法:什么闭包、回调、多态、代理、委托……随随便便都能玩出来。
如果说复杂度,那就是反过来了。
因为 C 在语法上没有对底层进行过多的封装和抽象,以至于把大量细节都繁琐的暴露在程序员面前。这个时候,要完成一个特定目的的功能,尤其是复杂点的功能,你有两条路可走:
1:自己不厌其烦的全部实现一遍——但大多数情况下,这都是无价值的重复劳动。这就是为什么都在劝“不要重复创造轮子”。
2:找个合适的库。这时你就会发现,实现类似功能,会有很多的选择,但那些选择,往往都有不少细节上的区别。而去筛选、鉴别这些库,本身也就成为一项挺费精力的工作。这也是为什么谁都知道不要重复创造轮子,但总是有人会这么干。
而其他的高层语言,大都在语言层面提供了额外的抽象/概念/封装/实现,那这种实现成本就会大幅减少,也就实现了在复杂度上的“简单”。
但是因为提供了额外的抽象/概念/封装/实现,所以必然会在语法等方面增加了复杂度,也就必然加大了在难度上的“不简单”:例如说你说到的“1+2”等于多少等。
因为你也说了“做大作业(算法实现居多)”,不能刻舟求剑不是?
看一句话,首先要看这句话是谁说的,其次要看这句话是在什么背景下说的
vczh 整天安利 C# 大法好,那是因为人家是从 C++ 一路过来的,比我们这些把 C++ 当成“带着 Class 的 C ”来写的渣不知道高到哪里去了
相比写起来就像“穿着冰刀在打过蜡的地板上跳舞”的 C++ 以及跟在 C# 后面抄各种特性还抄不好外加类型系统还不封闭外加泛型实现蠢爆了的 Java ,对于有一点面向对象语言基础的人来说,当然是 C# 学起来爽写起来也爽了,不推荐这个推荐啥?
别人说 Matlab 简单,那是因为真的简单啊
解释执行,不用等编译然后一遍一遍 Debug,简单不?
矩阵转置只要写一个'就可以了,跟线性代数课本写法都一样,简单不?
各种 ToolBox,你能想到的这里都有,现成的各种滤波、图像处理、信号处理算法实现,简单不?
自带绘图和可视化工具,数据处理完直接画一个漂亮的图出来贴到 PPT 里,简单不?
难道真的只有我觉得C的语法是最简明易懂的吗?
其实你的感觉没错,单论语法来说,C 的语法确实够简单了
在我的直观感受中,C的指针,变量,内存管理,位操作是最为直观的
“直观”这个就不好说了,还是得看你写的程序是做什么的
做算法题打 OJ ,那 C 是够直观的,上来开个长度 10000 的数组然后一堆 Struct 排开,指针想飞到哪里就飞到哪里,这酸爽,不敢相信
写操作系统,写什么内核模块和系统调用,写什么 DMA 驱动,操作内存地址多直观
处理数据呢?处理 Excel 文件呢?你用 C 裸写一个看看?Python 那边 import csv 已经搞定了估计这边还在处理换行符吧?
开一个测试用的 HTTP 服务器呢?用 Socket 从底层开始写? Python SimpleHTTPServer 在看着你
写爬虫?这就更没边了,反正我是没见过哪位用 C 语言写爬虫,当年我用 Python 写,以为凭借 requests 这种库开发效率已经够高了,后来才知道 C# 里面还有一个 webbrowser 类,谁用谁知道
反而是python的字典和类结构,繁复无比,玄而又玄。
不知道你说的“字典和类结构”具体指的是什么,不过 Python 那个作用域规则确实挺奇葩的,甚至有 global 这种关键字,字典之类的真没看出来繁复
而且当我发现一个变量竟然类型是自动的,当我想着1+2是等于12还是等于3的时候,怎么感觉所谓“简单易学的高级语言”反而更加“令人专注于过程而不是算法本身”了呢?
你最后一句话说的太对了,高级语言就是为了屏蔽那些浪费程序员时间的所谓“细节”,让人专注于高层的设计和逻辑。另外我很好奇,除了某些奇葩语言,没有其他语言把1 + 2的结果输出成12吧?当然如果你非要重载+号运算符那我没话说
总结一下,有几点:
语法的“简单”,只是评价一门编程语言“简单”与否的其中一个维度
这门语言有完备的标准库么?有的话写应用就简单啊
这门语言方便扩展么?有的话写 DSL 造轮子就简单啊
这门语言方便实行编程规范和协同开发么?一个 Java 老手读一个 Java 菜鸟的代码,跟一个 Ruby 老手读一个 Ruby 新手的代码,你觉得哪个会更困难一些?
这门语言方便兼容多范式么?你翻翻 Gtk 的源码,你觉得那种写法跟如今所谓的面向对象有多大区别?你看看 C++ 的模板,什么花儿玩不出来?
这么多维度,哪个可以用来判定一门编程语言是否“简单”?
做工程和做数据结构的大作业,对语言特性的要求是不同的
做数据结构和底层,那么无关的语法糖和封装越少越好,就是要有拳拳到肉的爽快感,既然程序猿知道自己在做什么,那么他就应该为他自己的代码负责
做工程,为了模块划分清晰以及协同开发,就需要各种封装,比如类,比如 Property,比如 Interface;为了加快开发速度减少浪费在重复造轮子上的时间,就要有各种标准库,拿来用就可以了,而且人家标准库一般比你自己写的要好得多
======================================================================
最后,对于觉得 C 语言易于上手的人,我一般都推荐两个办法:
一个是去玩任天堂的游戏,然后一边玩一边念:上手易,精通难
另一个是去翻 Linux 的源码,然后一边翻一边念:这里我看得懂
念到怀疑人生为止
======================================================================
评论里看到题主说“对,别人工程都做完了我还在困惑.net的方法,字段,事件都是个啥玩意”,于是补充一点
对于你的困惑,大概是两方面造成的
一是缺乏对于现代编程语言和编程范式的认识和理解
可以尝试着去看一些介绍面向对象的文章以及设计模式的文章,一边看一边想这里用 C# 可以怎么实现,C# 的那个特性是出于什么目的被添加进来的,然后结合工程实践加深理解
所谓的方法、字段、事件,这些编程范式或者编程模式,说到底也就两大块:抽象与封装
抽象指的是对现实世界的建模或者说模拟
有的人认为程序对现实世界抽象就是一个接着一个的流水线式操作,所以他们用 C,写上一个个的函数和流程跳转,然后管自己叫“过程式语言”
有的人认为程序对现实世界抽象就是一个接着一个的对象,对象之间协商接口,通过继承来模拟现实世界事物之间的关系,通过消息传递来通信,所以他们用 C# 和 Java,然后管自己叫“面向对象式语言”
有的人认为程序对现实世界抽象应该是函数运算与表达式,所有的操作都应该抽象成函数调用,所以他们用 Haskell,然后管自己叫“函数式语言”
还有的人不知道程序对现实世界抽象是什么样子的,所以他们管自己叫“多范式语言”
233
封装就更好理解了
一种封装是为了向上屏蔽底层的实现,对上层编程者透明,比如 JVM 封装了一个 Java 语言的运行环境,理想状况下我并不需要知道底层是 ARM Linux 还是 Windows;包括网络中的封装也是如此,不管是五层还是七层,都是为了屏蔽下一层的实现
还有一种封装是为了隐藏内部实现,比如我把数据都封装到类里面,你能调用我公开的方法,但是你不能瞎改我内部的代码然后大半夜打电话喊我说为毛老子的代码又崩溃了
还有一种封装是为了代码复用,写 C 语言写多了觉得这个快排没必要每次都写一遍吧,所以写个函数封装进去,下次直接调;写 Java 写多了觉得这几个类有共同的初始化操作,所以写个父类把init过程封装进去,几个类的差别用继承然后重载来实现
说白了就这么回事,多写点就懂了
二是其实是现在的一些编程书造成的,编程这个行当很多人有个“不说人话”的毛病
有的人是故意拽词来吓唬初学者,什么“模式”“范式”“思想”掉书袋一大堆,其实用大白话来说就是挺简单的事情
什么“轮询”,不就是“我过一会就去问问再过一会再去问问”的意思么?
什么“回调”,不就是“我告诉你如果某件事发生了该调用哪个函数”的意思么?
除此以外,还有些是为了描述的准确性不得不牺牲易读性
比如 Haskell 那个经典的梗“ Monad 不就是一个自函子范畴上的幺半群,这有什么难以理解的”
如果你去看一下自函子和幺半群的概念,你会发现这确实是对 Monad 最简明扼要准确的描述了
可是未免也太艰涩了吧?
所以我很希望能有人写一本书,用“说人话”的方式把一些编程的概念通俗易懂地介绍出来,可惜现在还没有见到,或许一些知名博主的博客已经部分有了这个功能
随夫姓不局限于发达国家,但全世界都大差不差。
婚后随夫姓,确实是体现了一种从属关系。如果按今天的政治正确,尤其是按女权思想,简直不可救药。而实际上,把目光放在历史长河当中,能随夫姓简直相当于进了体制内,属于铁饭碗待遇的体现!
苏轼牛不牛?其最爱的小妾,也就是被谪至黄州[1]都没有卖掉[2]的王朝云[3],坟头上也只能写着王氏,而非苏王氏[4]。
另外,关于姓氏,咱中国还略好一些,像日本,姓氏取的那么随意,也实在是没有办法!毕竟天皇到今天还没有姓氏[5],而平民拥有姓氏也只是近150年的事情[6]。姓氏上由于太随意,留下了很多奇葩的存在,例如"一二三、我孙子、肛门、猪鼻、上床、浮気[7]、土肥"……
名字就更随意了,男娃就叫大郎、次郎、三郎,至于山本五十六[8],咱也不敢说,咱也不敢问;女娃就是花子、美子、优子、菜子……并不比我们的大柱、二牛、小凤、翠花更高雅……
欧洲也没好到哪去,别看有些人名字里带个"Von/de/Don"之类的很显洋贵,其实11世纪之前这些贵族连姓都没有[9]。至于平民,那就更好办了,要么领个教姓/名[10],要么干脆看情况起一个,比如Fisher(鱼夫),Smith(铁匠),Hunter(猎人),Johnson(约翰之子),苹果CEO cook祖上大概率是厨子……
但毫无疑问的是,家庭作为社会中最基本的利益共同体,能否成为正式的家庭成员当然是极重要的硬指标。
在长久的旧时代,宗族/家族出身是极重要的,这是不分国界的。于女性而言,几乎不可能独立生存,如果再得不到家族的实名认证,人生大都是悲惨的。如果说有所区别,大概也只是悲惨的程度和花样。
现在回归问题身本:为什么如今在很多发达国家同样以随夫姓为主流呢?
先说,我国是破了四旧[11],烧了不知多少本家/族谱,否则也不会出现争冠姓权这种事。
一方面是惯性使然。这可不只是习惯问题,更不是简单的一句"传统观念"就能解释的。这种惯性,更多的是一种力量,是利益集团的一个标致,其中并非只有男权,而是整个家族的权力征徽,更类似于一家大企业的名号,其庇护作用是显而易见的。
而平民阶层随夫姓的主要原因是效仿权贵阶层,除了自觉拿到了"皇帝的金锄头",再就是"话事人[12]"原则的体现,也就是每家每户,都要有个撑门面的最强者,而普遍上兼具暴力与理性的男性显然更适合这个位置。就普通家庭而言,其实这个位置并没有多爽,责权一体不是说着玩的!如果放在中国,这个位置就更难坐了,很多中国家庭中享有冠姓权的男性,责任与实权、收益并不成正比。
这里面还有个逻辑推导,既从妻子的角度出发“我随他姓是因为他很强,也比我强,如果反过来,他随我姓就说明我比他强,反推就是他比我弱,如果我还不如多数随夫姓的女子,那则说明我们一家子都还不如别人家最弱的那个,那就没法混了呀!”
所以,姓氏对于小家庭意义并不大,但对家庭某一成员的意义很大。且随夫姓并不见得就亏,反而很可能是赚的,无利不起早,这符合人性中的趋利特点。
那一定有人问“为什么现在很多女性/女权还要争冠姓权呢?”
答案就是:不是姓氏有问题,而是人品有问题!
以上。