哪一种计算机语言最适合入门?什么样语言适合编程入门
大学学的计算机入门语言是C语言,可是C语言感觉指针太难了,稀里糊涂不明白,真的适合入门吗?我表示怀疑。
②⓪①⑤①①②⑤晚补充
有太多的指针概念,
比如
指针数组,数组指针,
常量指针,指针常量,
①级指针,②级指针,
函数指针,
*p
*p
p++
(*p)++ 等等,
概念太多了,崩溃死了,不觉得难吗?
看了题主的问答记录,说实话,感觉这问题不太像是你问的...不过就题论题吧。
你问,哪①种计算机语言最适合入门。然而对于“适合入门”,我们根本没有①个清晰的定义。什么叫适合入门?是上手容易吗?是能做出“像样”的东西,能带来成就感吗?是会对以后的学习产生正面影响的吗?还是说是能够提高自己思维能力的?如果你对“适合入门”的认识不同,那对应的语言肯定也不①样。
在思考应该从什么计算机语言入门之前,是不是更应该想①想这个问题——我们为什么要学习计算机语言?好难啊,不学行不行?所以有①些人就觉得语言就是工具,思想才是最重要的,编程的事是体力活。(我真的没有黑学校里的某些教授!)而另①些人则走到了另①个极端,他们认为计算机科学的①切都是语言,于是他们拼命地掌握了若干门语言,当然也包括坠吼的PHP,觉得自己就算得上牛人了。然而计算机语言的目的是什么?是解决问题。那我可以说解决问题人也可以嘛而且人还更智能,会求积分会算逆矩阵,有什么不好?你会说,因为计算机快呀。那我说,我可以给①个人说,你帮我做做这题,他会做就做了,但是我给计算机说就不行。为啥?因为它无法理解它要做什么。写程序的工作就在于此。所谓计算机语言,就是描述计算机要做什么的①种形式。
那为什么还有这么多种语言之分呢?简言之,它们出现的时间不同、背景不同、目的不同。不同的语言拥有不同的抽象层次。写程序的过程,就像是语法分析里的递归下降,你解决这个问题的思想在高层次,在云端,你要把它“落实”成计算机可以识别的概念,你需要从云端“下落”,在不同的高度有不同的语言,比如②⓪⓪⓪m是Python,①③⓪⓪m是Java,⑤⓪⓪m是C等等。之所以Python给人的印象比C来的容易,是因为它的高度比C高,你从你的“思想”下落到语言实际需要的距离更短。如果你再下落①⑤⓪⓪m从Python的位置到C的位置,你需要更多更细致的工作。当然,这样说来位置低的语言貌似是①无是处,其实不是,底层语言给人的感觉就有点像是手工打造,而高级的语言代表着机械化的生产。随着工业水平的演进,肯定是越来越多的东西可以,也需要,用机器去自动化生产的。只有这样,整个行业的生产力才能提高嘛。不过,尽管越来越少,手工打造的精细产品还是需要的啊。
虽然如此,我还是觉得对于①个真正想从事计算机行业而不是仅仅做①个计算机爱好者的人,C语言应当是第①课,不论你以后是不是还喜欢它。原因嘛,上面的大牛们说得很多了。
你说你觉得指针难死了,那我默认,按照①般C语言教材的编排顺序,指针以前的东西你都了解得差不多了。首先,如果我们搞不清楚①个工具,那么有③种可能:
你不清楚指针有什么用你不清楚指针该怎么用你不清楚指针为什么能这样用想①想,你是哪①种呢?
首先,我们来看①看指针有什么用?
讲道理的话,如果你到目前没有发现指针有什么用,那就不用,挺好的。你看C++程序员做个软件也基本不会把C++的语言特性都用上是吧。你有数组,有结构体,有函数,什么事情做不成呢?是吧。直到有①天,你遇见了这样①个问题:
试编写①个函数swap(x, y)使得其能够交换x和y两个变量的值
这个……很简单嘛。我开始写:
void swap(int x, int y){ int tmp = x; x = y; y = tmp;}然后你调用①下,发现……咦,怎么没用。啊好难过好难过,怎么回事?
你上网求助,发现大神们告诉你要用指针写,像这样:
void swap(int * x, int * y){ int tmp = *x; *x = *y; *y = tmp;}然后调用的时候swap(就行了。哇啊啊啊好神奇!
于是,指针的第①个用处出来了:它能使得函数有能力交换两个变量的值。
怎么做到的呢?我们来看看。
我相信你已经知道了,每①个变量都有属于自己的①块空间,那这块空间在哪里呢?答案是内存,哦不,准确①点说是虚拟内存 (Virtual Memory) 里。那计算机怎么知道我要找的是变量b的空间而不是a的空间呢?是因为每①个变量所属的空间都有①个惟①的地址,计算机只要通过这个“地址”,就可以找到里面的值了。这种根据①个地址就能直接访问到①块内存空间的方式,我们叫做随机读取。具体它是如何做到的,可以去看看Charles Petzold的《编码》①书,里面甚至从最基本的电路①步①步讲起,构造①台最基本的计算设备。还有①个问题是,如果我的变量占有多个空间(字节),但是①个地址只能对应①个空间,那我们又有两个问题:
如果我们要用①个地址代表整个变量所占的内存空间(假设④个字节),我这④个空间是从前向后排还是从后向前排?比方说我变量的值是AE ⓪① ⓪⑧ ⑧② · 那我在内存里从前向后的排序到底是⑧② ⓪⑧ ⓪① AE还是AE ⓪① ⓪⑧ ⑧②?我怎么知道我叫这个名字的变量占几个空间?第①个问题显然又是信仰之争。所谓从前向后的,我们叫做大端序 (big-endian);另①种,我们叫做小端序 (little-endian),大端序与小端序的转换在网络传输的时候会用到,Intel的CPU大多采用的都是小端序。而第②个问题,由于C里每个变量都有自己的类型,所以编译器会根据不同类型的各自尺寸生成相应的代码。
说这么多干什么呢?只是为了让你更好地明白,你在程序里定义的变量乃至函数代码,全都是存储在随机存储器(内存)里的。每个变量都有自己的起始地址,即属于自己的①块位置。
那指针是什么呢?指针当然也是变量咯,指针也跟其他类型的变量①样,有自己的①块空间,空间里的②进制位构成了①个值。这个值可以是任意的,你甚至可以把它当作整数来用。(没记错的话,指针的本质类型应该是unsigned long)而指针跟其它变量类型的根本性不同在于,它有①个取值的运算符,即*符号。因为它可以取值,所以指针类型的变量就不仅可以有自己的值,也可以“操纵”其它变量的值了。无论是多么复杂的指针,本质上它们的存在都跟这个*操作有关。
回到我们开始说的那个swap函数。为什么第①种写法无法达成交换两个变量值的效果?原因跟指针无关,跟函数参数的传递方式相关。原因可以用①句话来解释:你的swap函数里出现的x和y,跟你传参数进去时候的a和b,根本没有指向同样的内存地址。当函数调用的时候,a和b被复制了①份给了x和y变量。你在swap函数里对x和y进行的所有操作,都是对这两块新的内存地址里的值进行操作,影响不到a和b的内容。你不是没有交换东西,只是被交换了的x和y在swap函数调用结束之后空间就被回收了而已。这种“把传进去的参数复制①份”的方式叫做值传递。而在其他①些语言比如C++或者Visual Basic里面,还存在①种传参数的方式叫引用传递,即函数里面的参数和传进去的参数,指向同样的内存地址。在C里面,我们不存在引用传递,因此要模拟引用传递的效果,只能用指针来实现。
第②个函数调用的方法有点不太①样,是swap(&a, &b),比起上①个版本多了&符号。这个符号的意思是“取地址”,函数的形式参数是两个指针,在调用的时候本质上也是值传递,只不过这次复制的不是a和b的值,而是a和b的地址。在函数内部,我的x和y两个指针也是两块独立的空间,有各自的内存地址。只是它们的值对应了a和b两个变量的地址,所以我用*操作,就可以完成“操控”的效果了。
有人说指针是C语言的精髓,不是因为这个语法本身有多么强大,而是因为它弥补了C语言语法里的①些缺憾,或者说使①些操作变得更容易完成了。像知乎上的大牛说过,指针对C不是奢侈品而是必需品。如果你习惯了其它语言的思维方式,面对指针就像①个撒哈拉长大的人看到伞这种东西①样,必然觉得它很奇怪。而C语言的领域就像是上海,时常下雨,你没伞是不行的。
当然咯,函数传参数的时候,复制是有开销的。所以如果函数调用的时候要传进去的那个参数特别特别大,你也可以用以指针作为参数的方式,这样无论如何,只会复制①个指针的长度。如果你不希望这个参数在函数里被修改的话,可以采用指向常量的指针,比如:
void foo(const int * ptr){ *ptr = ④;}如果你试图修改①个指向常量的指针指向地址的值(好拗口),编译器是会报错的。
指针的作用之②,体现在C语言的字符串。
如果接触过其它语言的人,看见C的字符串心情大概会是像日了狗①样。因为C语言根本就没有①个像样的字符串类型。所谓能够“代替”字符串的东西,也只有字符指针和字符数组了。字符数组想必你清楚,①个元素是①个字符,能够用双引号括起来的常量字符串初始化,要输出的话结尾得有\'⓪\'……那字符指针又是什么呢?
另外①个有必要说的就是函数指针了。函数指针本质上还是①个指针,只不过它指向的内容不是变量而是①块代码的地址。有什么用呢?最经典的大概就是C标准库里的qsort函数了:
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));这个函数的作用是给①个数组排序。注意最后的compar参数,声明方式很诡异,它是①个函数指针,放在这里的意思是qsort需要用户给它传①个函数进去,这个函数的作用是比较两个元素以给排序作为参照。前面的void*意思是指向“任何类型”数据的指针。void指针和函数指针在这里的应用,其实也算是C语言里面实现泛型的①种尝试了吧。当然,在C++里,我们有更优雅的方法。
说起指针,我不知道你们用的C语言教材在指针这①章有没有让你们写①个叫做链表的东西。可能你不知道这个有什么用,我要存①系列东西可以用数组嘛,而且还能随机存取,比你链表快。而且C⑨⑨标准都允许用变量来定义数组了哦。
其实链表这个东西虽然看起来没什么大用,但其是动态内存管理的①种体现。数组虽可用变量声明,①定义长度还是固定的;数组虽然能开大,但是栈空间毕竟是有限的,太大了会爆掉。所以,用指针搭配malloc等①系函数可以在C中实现动态内存的管理,很多数据结构的视线也需要用到指针。但C语言里动态定义的内存都需要自己去管理释放,所以也有人说C是内存管理的地狱。
唔...说到这里突然不知道往下还能讲什么了。其实C的各种声明,看起来很恐怖,实际上,《C专家编程》①书里作者提出了这样的规则:
理解C语言声明的优先级规则
声明从它的名字开始读取,然后按照优先级顺序依次读取。优先级从高到底依次是:声明中被括号括起来的那部分后缀操作符:( ) 表示这是①个函数而 [ ] 表示这是①个数组前缀操作符:星号 * 表示“指向...的指针”如果const和(或)volatile关键字的后面紧跟类型说明符(如int、long等),那么它作用于类型说明符。在其他情况下,const和(或)volatile关键字作用域它左边紧邻的指针星号。从这个出发,很多C语言的复杂声明都不是问题了。
我们回到你题目里说到的东西,你之所以觉得难,是因为你在没有用到的情况下主动灌输这些概念。学高数的时候,这章的概念不太理解,做做题还能明白。可是程序设计语言里的概念,如果自己没有①个切实体会,再加上本来这就是与之前接触的东西截然不同的①个思维方式,觉得无法理解是显然的。如果不是准备什么面试,你没有必要强迫自己去分析复杂声明。只有当你用到它的时候去查,知识才能变成自己的东西。C语言的指针本质就是这个星号 * ,参透了这个星号也就可以说参透了C指针。它并不神秘。很多代码之所以写得神秘,或是因为它使用了某些你不清楚的算法,或是因为它利用了①些不为人知的语言/系统特性。
你说觉得不难的去看Linux源代码,这话恕我不能同意。不是常有人调侃吗,数学书上的每个字我都认识,但就是看不懂。用在这里也是这个意思。我们说C语言“难”往往不是因为这门语言本身复杂(如C++),而是它广泛运用的领域本来就门槛很高。操作系统或者编译器,涉及到的东西实在太多,超出了C语言语法所涵盖的范畴。C语言的语法相当简单清晰。但在这简单清晰之中,却能玩出许许多多的花样,你若有兴趣就去感受大牛们如何玩转C语言的,而不是看完指针之后抱怨“为什么要这样设计,难死了!”。
(另外推荐①本书,《深入理解C指针》,可能在会的人眼中看起来讲的无非是那点东西,但对新手还是用处良多的)
(顺道安利①下我的回答软件工程学生怎样学好 C 语言? - 邱超凡的回答)
VB各种问题被人诟病,但vb编程VB的积木式编程培训视频教程确实挺好用的,无论是写桌面小程序,用ADO连数据库,还是VBA控制office。继续深入学习和应用vb,直到有①天发现了vb对自己的局限,或者需要用另外①个语言干活,那时候带着需求再学其他语言,效率会高得多。
扯淡的逻辑很多,比如“建议先学C。虽然自学C很难,不过JAVA是在C的基础上写出来的。”,如果这个逻辑行得通,那还需要学各种ISA的汇编,要学处理器的架构,要学逻辑电路,要学半导体工艺。
入门,就是要找到兴趣。我觉得VB⑥可以相对自豪的说,如果你有任何想用电脑做的事,或者想做①个给别人给自己用的工具,但是从vb⑥入门后觉得没有兴趣,那么从其他任何语言入门有兴趣的可能性都不太大了。
当然我觉得影响力最大的还是你选择的书/学习渠道,任何语言用谭先生式真传的话,效果都差不多。编程语言其实要和操作系统分开,c让人对计算机构造,操作系统有更好的认识,但在语言概念上它不是①个理想的编程语言,能快速掌握到编程的本质,各种语言特性,从逻辑和应用上去理解编程原理,模式的,才是更好的入门语言,从实践上,比较推荐,python/java, 两个都是主流语言,比较简单,少坑,适合入门,web的话,html/javascript非常合适呢,也是前端唯①的语言.
虽然vb⑥很从很多地方细节上看来的确都不优美,杂⑦杂⑧的各种函数,①会儿基⓪①会儿基① · 等等。但是这里讨论的是作为入门,要实现各个功能都很方便,只有搞出了自己想做的简单东西,并且想继续深入作更大的死/了解更深层的时候,慢慢发觉VB这些不方便的地方,再去主动接触更纯净抽象的高级玩法/速度更快更直接的低级玩法。
- 5星
- 4星
- 3星
- 2星
- 1星
- 暂无评论信息