楔子:C有很多版本,最早接触的是TurborC,大一就开始学,当时写过链表结构的班级数据库,把鼠标做成女友的名字,整个屏幕的雪花,简单动画。可惜的都是Console下运行的程序。到了大二开始学习C++教程,自从安装了VC6.0以后就很少再使用C来写程序了,也不知道C和C++的区别是什么。只当成C++把C兼容了。但是实际还是有区别的。毕业后学习了AVR单片机,开始使用GCC编辑器。和大学时看到的8051的C感觉是不一样的,其实我没有真正做过8051,只是学习过,所以有理解错误的话希望被指正,指正必更改。8051当时记得指针是三位的,而且一些变量需要使用8051的声明结构。最后感觉还是GCC比较好用。后来毕业后处于茫然之中,就什么都想学,花了三个月时间搞懂了MFC原理,结果却被ARM的引入给搁浅了。偶然的机会让我发现了ARM处理器,并对它产生了强烈的兴趣。兴趣是这样来的,毕业后从事产品生产工作,但是单片机的速度让我越来越不满足。尤其是接触到USB之后,给了我开发的欲望,但是苦于当前手上的Atmega16只有8M速度,苦读USB协议后,终于发现了ARM,当我下定决心该学ARM时,周围一些人对我说:ARM很难的。但是兴趣来了,谁也挡不住的,下定决心要学ARM了。在研究ARM架构和汇编指令的两个月后,本已负债的我从信用卡中取出600元购买了一块S3C2440为核心的ARM9开发板。从此了我的ARM之路,也开始我的Linux之路,最后的结论是,其实ARM并不难,Linux其实也不难,只是太少人愿意去做了。现在ADS1.2和Arm-linux-gcc就是我主要的C编辑工具。在开发ARM7时还使用了Keil编辑器。好了,废话就那么多,接下来进入正题,这些是我的个人总结和感悟,这是我的财富,所以绝无任何刻意抄袭。如有雷同,纯属巧合。就如美的空调和格力空调一样,都使用压缩机,都是由两部分组成。最后重申一句,如有错误,请指出,指出必更正。
声明:本人将不会对其中的错误对你造成的损失负有任何责任,学习C语言和C++请参考正规渠道教科书。
1.C是面向过程的语言,这点是和汇编一样的,C的出现极大的简化了代码,我的感觉主要来自于两点: 一.C中的数据结构是一个伟大的发明,将全局变量单独放在代码后面,使用栈来分配局域变量。利用类型来表示变量占用的空间大小。如有不明,可查询相关资料了解这些列出的概念:代码段,只读数据段,可读写数据段(初始化部分和未初始化部分),栈。C语言语法涉及内容:全局变量,静态变量,局域变量。 二.使用栈来管理局域变量和函数调用,C语言是不允许跨函数跳转的,因为那是一个极危险的举动,将会破坏所有保存的栈结构。这种机制同时也解决了临时变量空间的问题。 现在来说下C语言执行顺序,C语言执行首先需要一个入口函数,从这个入口函数处开始顺着程序顺序朝下运行,遇见函数则为该函数在当前栈上开辟临时变量空间,并将当前栈指针下移,继续顺着程序朝下运行,再遇见函数时继续为该函数在当前栈上分配该函数所需临时变量空间。当函数运行结束后,栈会收回为这个函数在栈上分配的变量空间,并返回调用函数后继续朝下运行。这就是C的运行流程,当然,我们是不会让程序从上往下一直到退出的,一般至少有个while循环。 注意:以上所说的栈为进程做什么什么,栈指针下移都是为了理解流程,实际上处理器的栈是不可能自己移动的,他是C语言汇编的一个机制,当汇编一个函数时,编辑器会计算函数需要用到的空间大小,然后在函数头部和尾部加上一些汇编代码,控制栈指针的移动来实现分配和释放。另外,上面所说的函数不全面的,只是觉得大部分人对函数的认识要比较深刻些,实际上应该是用域来表示。两个大括号括起来就可以看做一个域,函数是使用大括号括起来的,所以是一个域,但是程序内也可以直接用大括号括起来,这个就是域了,域包括函数,但是函数不代表域。见下面使用方法 int main(intargv,char*argc[]) {//函数域 int i; show(i); Int x="sum"(5);//这是不允许的 {//子域 Int i; Show(i); } return0; } 我们知道,C语言是不允许在执行语句间声明的,如例子中的变量x声明就是不合法的,但是在域的开始声明就可以,在域中可以重新声明变量和使用函数变量,但是有一点,如果重名的话C语言会使用子域中的变量。C将子域看做一个块来执行。 最后来说下为什么说C语言是面向过程的,如果单步调试的话,你会发现C语言只有两种运行方式:按指令顺序运行;函数调用,调用后返回。然后我可以说:C语言是按照语言的顺序一步一步开始执行的。他的行为通过他的执行顺序表现出来,就像我们做事一样要有个顺序,先做什么,再做什么,然后做什么,所以说C语言是面向过程的。 究其以上还可以得出结论,靠C语言是永远做不出系统的,系统需要切换进程,切换进程需要修改栈,但是C语言是保护栈的。
2.C++是兼容C语言的,但是却是面向对象的程序语言,C++的英文名读作C plus plus。 对象的概念就好比一个人,人要名字,有身高,有专业,然后他能吃饭,唱歌,睡觉。对象的使用包括三个方面: 一.创建一个对象类型,如上面的例子,人,这是一种抽象,也是一种概念。 二.创建一个对象,就像声明变量一样声明一个对象。如声明一个人类型的对象,然后就可以操作人的属性了,如让他吃饭,唱歌,睡觉。 三.编辑器要能识别对象,当发现声明一个变量时,要搜索这个对象的类型是否需要初始化。如发现程序中创建一个人时,要调用对象人的初始化函数来给人赋予一定的特性,如人是地球上的。在地球上要为他保留一个空间。当撤销人时要调用对象人的撤销函数来收回这个人占用的地球空间。 C++要比C赋予了更多的智能,其最主要的贡献者就是编辑器。学C的时候我们主要就是编写语言,因为它所有的特征都体现在语言上,但是对于C++,和JAVA等高等语言语言,编辑器会很好的帮你做打理程序顺序。
2.前面说过C++是兼容C的,但是C++是不能直接调用C程序的。至于C如何调用C++程序也,我不知道。一般的解释是由于C++支持函数重载,而C不支持函数重载造成的,实际上是由于C++的函数命名和C的函数名字在汇编后不同造成的。C语言汇编后函数名不变,而C++程序在汇编后会把函数名和输入参数类型一起组成函数名。C和C++语言再被编辑成目标文件前都需要先汇编成汇编文件。C++编辑器在调用函数会自动加上函数类型,这样就可以找到对应的函数了,而C语言就没有这个机制了。 对于C++调用C函数,要在函数前加生命extern“C”{//函数},这样C++就可以调用C库中的函数了,这个声明告诉C++编辑器这个函数是C函数,不用修改函数名
3.下面就开始讲述一些C++的智能部分了。 a)类毫无疑问类是C++区别C最具有代表性的一个了,也就是传说中的对象。类包括两种类型成员:类变量和类函数。每创建一个函数时,就会为函数分配全部类变量,只有该类的对象才能使用该类的类函数,类函数可以直接操作该类的所有类变量。类成员按照使用权限可分成私有成员和公共成员和保护成员。该类类函数可以操作所有成员,但是通过类名只能访问公共成员和保护成员。按照功能又可分为:普通成员,构造函数,析构函数。声明类对象时会调用类构造函数,用于初始化创建的类,在类生存域内可以通过类名使用类普通成员,然后在类退出类域名时会调用类析构函数,可用于释放资源等。另外,类还可以通过三种方式继承,私有方式,公共方式,保护方式。无论那种继承编辑器都会找到最顶层的父辈然后依次创建对象,组成一个对象组。比较特殊的继承方式是虚继承,主要为为了避免重继承创建的。如果A继承了B,C两个对象,而B和C都集成D,如果不用虚继承,就会创建两个D,对B和C使用虚继承D,就会只创建一个D。另外还有虚函数的概念。其实用起来时很简单的,主要是讲述起来复杂。网上都能搜出资料来。
b).C语言提供API供调用,C++提供开放的类供调用
c).函数重载和函数模版,C++支持函数重载,即允许相同名字的函数,但是参数不一样的函数同时存在。在调用函数时,编辑器会根据参数的不一致调用对应参数的函数,另外,函数调用支持在声明时赋予一个初始值,如intsum(int x="10");调用时如果函数没有参数,编辑器会帮你传入10作为sum的输入函数。另外关于C++的模版看起来时很复杂的其实使用起来是很简单的
d).new和delete关键字,对于这两个关键字,总有人喜欢拿他们和C库函数malloc,和free比较。Malloc,和free等一系列函数在堆上分配内存,而new和delete在自由区分配内存。不管在哪分配,效果是差不多的,最重要的一点差别是,malloc和free是库函数,只能执行分配内存,没有附加属性,new和delete是编辑器关键字,编辑器看见它,不只会为他分配内存,还会检查属性,如果是类对象,编辑器会调用类对象的构造函数。
e).this指针,用于指明这个变量是属于当前对象的的,常用例子就是this->i=i;
f).类函数指针,主要是类函数的函数指针,要加上类作为域名,表示这个函数指针是之指向类成员的,如Type(classname::*functionname)(param…).声明的时候有点注册的意思,functionname=&(class::functionofclass)。调用这个函数必须有类实体.(Classentry.*functionname)(param).效果和Classentry.functionofclass(param).不同的是类函数是由编辑器检测可用,然后通过在内存中提取函数指针调用函数,并指明可操作参数,而后者是编辑器全部帮你调用函数,输入参数。
g).类中的static成员,属于所有类的,只在开始创建一次,创建类对象时不再创建静态成员,但是却可以使用静态成员,Static类变量必须进行初始化,不分权限使用typeclass::Varient=Value初始化。对于静态类函数唯一感觉到差别的就是静态类函数不能使用普通类成员,只能使用类中的的静态成员。
h).最后一点C++还和C不同的是,C++不再限制只能在函数开始处声明变量,C++可以在任意地方声明变量,如果你使用int x,int y,然后调用cout<<&x<<&y,会发现,x和y得地址不是连续的。C++在只在使用变量的时候才会为变量分配空间。所以常有下面用法 for(inti=0;i<100;i++) 4.引导代码:很抱歉,对于C++引导代码,至今还不是很清楚,对于C引导,需要以下几步: a)将代码放到正确位置上,及编辑时我们使用了什么地址,就把代码拷贝到什么地址上 b)将初始化数据区放到正确位置上。 c)将未初始化数据区清零。以上都是准备内存工作 d)设置栈值,根据所需要使用的内存空间,设置栈指向内存空间的顶 e)跳转到C语言入口处开始执行
5.书写格式,其实写代码是没有固定格式的,只要你看多了就会熟悉,但是为了便于别人阅读,也为了便于自己读取别人的代码,所有大家一般都会向两个风格靠拢,VC风格的和Linux风格的。这个每个公司可能都会有很多差异,我只举例说明一下 a)命名规则: i.组成:ASCII字符,数字,下划线,其中,数字不能开头 ii.变量名:可以加小写前缀i,g,p,u8,u32,f,d,暗示类型或位置。 iii.函数名:一种是第一个字母大写,如GetValue,一种是加下划线Get_Value前面加一个或两个下划线的函数表示不要轻易改动的函数。 iv.预定义:全部大写,要避免和文件名相同 v.备注:不喜欢使用中文拼音命名的人,如diyici,dierci b)函数声明: i.使用static暗示此函数和变量只在此文件域或函数域内有效 ii.头文件中尽量少用extern声明函数,在C文件中声明extern函数表述引用外部函数。 iii.使用config.h作为配置文件,commom文件作为常用头文件,调用type.h,string,h,stdio.h,error.h等常用但是不会轻易修改的文件 c)数字尽量通过预定义或enum使用英文名称 d)常用”Tab”键盘 e)使用预定义命名特殊文件名,如#define Version“Linux2.6.22.6”
5.关于C和C++还有很多特殊用法,限于篇幅和本人学识有限,就到此为止,感谢您能利用您宝贵的时间来匆忙一瞥,希望没有耽误您更多的时间。
|