1.C语言之父是丹尼斯·里奇,他不仅是C语言之父还是UNIX之父;
2.C语言的三个特点(为什么嵌入式的开发选择C语言为开发语言)
(1)运行的效率高:C语言的目标代码效率一般只比汇编程序低10%~20%,因此在同类的语言中,C语言具有生成目标代码质量高、程序执行的效率高的优点。
(2)代码的移植性好:C语言有一个突出的优点就是适用的范围大,适合于DOS,UNIX、Linux、Windows等多种操作系统也适合与多种的机型。只要将一个硬件型号下的程序稍加修改,甚至不加修改,就可移植到另一个不同的硬件型号开发环境使用,这样,方便了程序的移植和代码重用。
(3)可以直接对硬件进行操作:由于C语言允许直接访问物理地址,可以直接对硬件进行操作。这是它既有高级语言的功能,又具有低级语言的许多功能的重要表现。C能够像汇编语言一样对位,字节和地址进行操作,而这三者是计算机最基本的工作的单元,可用来写系统的文件。
另外,C语言具有强大的图形的功能,支持多种显示器和驱动器,且计算功能、逻辑判断功能强
3.
1.编译
编译型语言写的程序执行之前,需要一个专门的编译过程,把程序编译成为机器语言的文件,比如exe文件,以后要运行的话就不用重新翻译了,直接使用编译的结果就行了(exe文件),因为翻译只做了一次,运行时不需要翻译,所以编译型语言的程序执行效率高,但也不能一概而论,部分解释型语言的解释器通过在运行时动态优化代码,甚至能够使解释型语言的性能超过编译型语言。
最典型的例子就是C语言。
2.解释
解释则不同,解释性语言的程序不需要编译,省了道工序,解释性语言在运行程序的时候才翻译,比如解释性basic语言,专门有一个解释器能够直接执行basic程序,每个语句都是执行的时候才翻译。这样解释性语言每执行一次就要翻译一次,效率比较低。解释是一句一句的翻译。
此外,随着Java等基于虚拟机的语言的兴起,我们又不能把语言纯粹地分成解释型和编译型这两种。
用Java来举例,Java首先是通过编译器编译成字节码文件,然后在运行时通过解释器给解释成机器文件。所以我们说Java是一种先编译后解释的语言。
再换成C#,C#首先是通过编译器将C#文件编译成IL文件,然后在通过CLR将IL文件编译成机器文件。所以我们说C#是一门纯编译语言,但是C#是一门需要二次编译的语言。同理也可等效运用到基于.NET平台上的其他语言。
4.
面向过程一种以事件为中心的编程思想,以功能(行为)为导向,按模块化的设计,就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
面向对象一种以事物为中心的编程思想,以数据(属性)为导向,将具有相同一个或者多个属性的物体抽象为“类”,将他们包装起来;而有了这些数据(属性)之后,我们再考虑他们的行为(对这些属性进行什么样的操作),是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
面向过程和面向对象的区别 面向过程适合处理简单的事情,直接关注流程,简单有效。 面向对象适合处理复杂的事情,先使用面向对象的方式对整体关系作出分类,然后,根据不同的类深入细节的处理。 面向过程和面向对象的联系 面向对象无法取代面向过程,他们是相辅相成的。面向对象关注于从宏观上把握事物之间的关系,在具体到如何实现某个细节时,仍然采用面向过程的思维方式。 面向对象如何离开了面向过程,就无法实现真正的落地,成为无源之水。 面向对象技术的优点 面向对象技术具有程序结构清晰,自动生成程序框架,实现简单,维护简单,代码重用率高,软件开发效率高等优点。
5.
在c语言中,可以用结构+函数指针来模拟类的实现,而用这种结构定义的变量就是对象。我们可以在头文件中声明,在c文件中真正定义,这样可以隐藏内部信息,因为外部不知道对象所占内存的大小,所以不能静态的创建该类的对象,只能调用类提供的创建函数才能创建。这种方法的缺陷是不支持继承,因为子类中得不到任何关于父类的信息。
在c语言中,可以利用“结构在内存中的布局与结构的声明具有一致的顺序”这一事实实现继承。
在c语言中我们可以用万能指针void*来实现多态。
6.
sizeof和strlen的区别:
1.sizeof是个关键字,因此,sizeof后面是变量名时可以不加括号,而strlen是个函数,必须加括号
2.sizeof是判断参数所占的内存大小,参数可以是类型,函数,而strlen有点像计数器,从某个内存地址开始计数,碰到"\0"时结束计数,参数只能是char *
3.sizeof编译时确定,strlen时运行时确定
4.在调用函数中,数组名作为形参的,会被编译器当成指向数组首地址的指针,因此作为sizeof的参数时等价于计算指针的大小,作为strlen()的参数时意义未改变
数组和指针的区别:
1.定义时,当等号右边为字符串时,数组是是分配在非常量区,指针指向的字符串被分配在在常量区(只读),因此数组可通过下标更改其值,指针不可更改!
2.占用的空间大小不同,数组占用所申请的内存大小,指针为4个字节(假定计算机的寻址大小为32位)
7.
gets()函数总结:
(1)gets() 从标准输入设备读取字符串,以回车结束读取,使用'\0'结尾,回车符'\n'被舍弃没有遗留在缓冲区。
(2)可以用来输入带空格的字符串。
(3)可以无限读取,不会判断上限,因此使用gets不安全,可能会造成溢出(打印时候出线段错误)
scanf()函数总结:
(1)scanf() 以 空格 或 回车符 结束读取,空格 或 回车符 会遗留在缓冲区。
(2)不能直接输入带空格的字符串。
注意:scanf()函数如何才能输入带空格的字符串,应使用:【具体代码和输出内容如下:】
scanf("%[^\n]", a); //%[]输入字符集, [^\n] 表示除了'\n'之外的字符都接收,即可以接收空格,这个可以用来输入带空格的字符串
9.声明:告诉编译器变量的类型 在哪里 或者函数的特征(返回值 参数类型 个数)
定义:告诉编译器 在此处分配存储空间 建立变量和函数
10.
在C语言中,对变量的存储类型说明有以下四种:
auto 自动变量
register 寄存器变量
extern 外部变量
static 静态变量
所谓存储类型是指变量占用内存空间的方式,也称为存储方式。变量的存储方式可分为“静态存储”和“动态存储”两种。
静态存储变量通常是在变量定义时就在存储单元并一直保持不变,直至整个程序结束。动态存储变量是在程序执行过程中,使用它时才分配存储单元,使用完毕立即释放。典型的例子是函数的形式参数,在函数定义时并不给形参分配存储单元,只是在函数被调用时,才予以分配,调用函数完毕立即释放。如果一个函数被多次调用,则反复地分配、释放形参变量的存储单元。从以上分析可知,静态存储变量是一直存在的,而动态存储变量则时而存在时而消失。
我们又把这种由于变量存储方式不同而产生的特性称变量的生存期。生存期表示了变量存在的时间。生存期和作用域是从时间和空间这两个不同的角度来描述变量的特性,这两者既有联系,又有区别。一个变量究竟属于哪一种存储方式,并不能仅从其作用域来判断,还应有明确的存储类型说明。
自动变量和寄存器变量属于动态存储方式,外部变量和静态变量属于静态存储方式。在介绍了变量的存储类型之后,可以知道对一个变量的说明不仅应说明其数据类型,还应说明其存储类型。因此变量说明的完整形式应为:存储类型说明符 数据类型说明符 变量名,变量名....;
总结与区别:变量根据定义的位置的不同的生命周期,具有不同的作用域,作用域可分为6种:全局作用域,局部作用域,语句作用域,类作用域,命名空间作用域和文件作用域。
从作用域看:
全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包含全局变量的定义的源文件需要用extern关键字再次声明这个全局变量。
静态局部变量具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束一直存在,它和全局变量的区别在于全局变量对所有函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。
局部变量也只有局部作用域,它是自动对象(auto),它在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。
静态全局变量也具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它文件里,不能作用到其他文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同名字的静态全局变量,它们也是不同的变量。
从分配空间看:
全局变量,静态局部变量,静态全局变量都在静态存储区分配空间,而局部变量在栈里分配空间。
全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一个源程序的其他源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其他源文件中引起错误。
(1)静态变量会放在程序的静态数据存储区(全局可见)中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。
(2)变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。
对于register变量的注意点:
1.用register修饰的变量只能是局部变量,不能是全局变量。因为全局变量的生命周期是从执行程序开始,一直到程序结束才会终止,而register变量可能会存放在cpu的寄存器中,如果在程序的整个生命周期内都占用着寄存器的话,这是个相当不好的举措,CPU的寄存器资源有限,因此不可能让一个变量一直占着CPU寄存器。(编译时候报错)
2.register变量一定要是CPU可以接受的值。
4.不可以用&运算符对register变量进行取址。
5.register只是请求寄存器变量,不一定能够成功。
11.
1.存储位置不同:全局变量存储在方法区,局部变量存储在栈区
2.生命周期不同:全局变量的生命期和主程序一样,随着程序的销毁而销毁,局部变量在函数内部,函数退出了就不存在
3.使用方式不同:全局变量在声明后程序的各个部分都可以用到,但是局部变量只能在局部使用。函数内部会优先使用局部变量再使用全局变量
4.未初始化的全局变量为0,未初始化的局部变量为垃圾值
12.全局变量可分为静态全局变量和普通全局变量,两者生命周期都是从定义开始到程序运行结束,都是存储在数据段
静态全局变量只在本源文件可见,其他文件不可访问,普通全局变量在其他原程序中声明为extern变量后就可以使用
13.变量:存储位置, 生命周期, 初始化(未初始化的静态局部变量,未初始化的静态全局变量和未初始化的全局变量,都为0,未初始化的局部变量为垃圾值)
函数: 静态函数
在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。
定义静态函数的好处:
<1> 其他文件中可以定义相同名字的函数,不会发生冲突
<2> 静态函数不能被其他文件所用。 存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期。 auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。
关键字extern和static用来说明具有静态存储期的变量和函数。用static声明的局部变量具有静态存储持续期(static storage duration),或静态范围(static extent)。虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。
14.
动态存储方式
所谓动态存储方式是指在程序运行期间根据需要进行动态的分配存储空间的方式。
动态存储变量是在程序执行过程中,使用它时才分配存储单元, 使用完毕立即释放。
静态存储方式
所谓静态存储方式是指在程序编译期间分配固定的存储空间的方式。
该存储方式通常是在变量定义时就分定存储单元并一直保持不变,
直至整个程序结束。全局变量,静态变量等就属于此类存储方式
分为静态全局,全局,静态局部,局部四个来阐述区别
15https://blog.csdn.net/fynjy/article/details/48195325
若在内存中,则数据可以”随机存取”,但内存数据被读取或写入时,所需要的时间与这段信息所在的位置无关.但是在读取和写入磁盘时,其所需要的时间与位置就会有关系.因为在BASIC,PASCAL和C/C++语言中,数组的存放是按照行优先来存放的,按行号第一行第二行…以此类推.本体关键是考察内存抖动的问题,如果按列访问则需要跳过一大串内存地址,这样可能需求的内存地址不在当前页中则需要进行页置换,这样便需要硬盘IO,减低速度.