码迷,mamicode.com
首页 > 编程语言 > 详细

Ubuntu的多文件编译以及c语言的数组、函数

时间:2016-07-24 13:34:50      阅读:415      评论:0      收藏:0      [点我收藏+]

标签:

  闲言少叙,直接切入主题。

  一、Linux下的多文件编译(Ubuntu系统)。

  对于小程序来说,往往一个.c文件就足够了,里面包含了各种主函数和功能函数,以及函数的声明等等。但是这样的弊端主要有两点,一是可读性较差,所有程序都在一个文件中造成检查和分析时候很不方便,特别是对于较大的工程来说,是无法想象的。第二点就是保密性,在工作中,我们要将程序交给客户,但是我们并不想让客户知道我们的源代码,所以要用这种方式将功能函数以.o的文件(二进制码)交给客户,确保自己的劳动成果不被别人剽窃,可以做到保护知识产权。

  说明了缘由,接下来具体介绍多文件编译。一般我们将文件分为三类,第一类是.h的头文件,第二类是.c的主函数文件,第三类是.c的功能函数文件。头文件用来存放各种函数的声明,主函数是调用功能函数来实现工程需求,功能函数文件是用来存放各种实现各种功能模块的函数定义。

  头文件的作用就是在预处理时候将头文件的内容放在有#include包含的地方。#include后面跟着的头文件有两种形式,一种是<>,一种是“”的形式,如:

#include<stdio.h>

#include"stdio.h"

  第一种是去默认的目录去寻找该头文件,第二种是先在当前目录下去寻找该头文件,若当前目录没有,则去默认的目录去寻找。

  在Ubuntu下用gcc进行多文件编译的命令形式是gcc main.c fun.c -o fun生成的fun就是编程出来的可执行文件。

  二、extern和static

  sxtern是修饰符,可以用来修饰变量或者函数。它的作用就是调用外源文件中定义的变量和函数。比如说我在a.c文件中定义了一个全局变量int hello = 0,那么我要是想在b.c文件中调用这个hello变量,那么我就可以在b文件要引用的地方声明extern int hello就可以在该作用域下使用hello这个变量了。这里需要注意的是extern int hello是声明这个变量,并不是定义这个变量,c语言不允许重载,所以不能重复定义。

  static同样也是修饰符,用来修饰变量和函数。在用来修饰全局变量和函数时,他的作用和extern是相反的,static修饰的全局变量和函数是禁止外源文件调用,比如我在a.c文件中定义一个全局变量static int hello,那么我想在b.c文件中引用,我使用extern int hello,并且使用,程序在编译的时候会报错。

  static在修饰局部变量时,会将该变量和全局变量一样存入静态存储区,他的生存周期和全局变量一样,一直到程序运行结束才被释放,但是该变量的作用域仍然是原来的作用域,比如一个变量是fun()函数中的一个局部变量,那么在函数调用结束后,该变量就不能使用,当再次调用该函数的时候,该局部变量任然是那个地址,,存储的还是那个值。

三、数组

  首先,数组的本质是连续的内存。

  数组就是开辟了一段连续的内存来存储相同类型的数据。int a[10]就是开辟了是个int型的空间来存储十个int型的数据,所以数组a占用的内存空间就是四十个字节。

  数组的初始化可以分为全部初始化和部分初始化,数组也只有在初始化的时候才能全部赋值,初始化之后只能一个一个赋值或者采用字符串输入scanf(%s,a)的方式进行整体赋值。部分初始化时,没有得到数值的空间默认是0,是绝对的0,不是字符‘0’。这个0也就是‘\0‘。说到这,就可以引用字符串数组的概念。字符串数组本质上也是数组,我们可以采用这个方式来初始化字符串数组:char a[10] = "abc",这种初始化等同于cha a[10] = {‘a‘,‘b‘,‘c‘,‘\0‘},可以看出,字符串数组的初始化会在结束时加一个’\0‘,在c语言中,字符串与连续字符的区别就在这里,字符串是通过最后的‘\0‘来判断该字符串是否结束,也就是说,‘\0‘是字符串的结束标识符。当用%s输出字符串时,就是输出到‘\0‘为止,且‘\0‘不输出,统计字符串长度(strlen()函数)也是一样,‘\0‘不统计在内。在用scanf输入用%s的方式输入字符串时,会在敲下回车的时候结束字符串的输入,此时会在将字符串最后的那个字符后面加一个‘\0‘作为字符串的接鼠标识。而回车并不会存入字符串中去。

  这里提一下二维数组,二维数组本质上和一维数组一样,都是连续的内存,只是二位数组就是将一维数组分段,然后二维数组的特点就是既可以方便的一个一个访问,也可以方便的一段一段访问。

  数组中还有一个重要的概念就是数组名。如char a[ 10 ] = {0};a就是这个数组的数组名,她就代表了这个数组。可以将数组名a理解成一个指针常量,注意这里的常量,因为数组名并不占内存,仅仅是一个形式而已,所以a++这样的操作都是错误的,编译也是不会通过的。但是在用数组名访问里面的数组元素的时候,她又和指针一样,可以用解引用(*(a+i))访问,也可以用下标方式(a[i])访问,而且这两种方式是等同的。这里需要注意的是数组名在两种情况是比较特殊的,比如用sizeof(a)操作时,如果a是指针,那么得到的是4(32位系统)或者8(64位系统),而如果a是数组名的话,那么得到的是数组a占用的内存空间,这里是10,这是一种情况,而另一种情况是&a,照理来说a不占用内存,&a应该是空,但是c语言中将&a的操作认为是取数组a首元素的地址,&a的值和a的值是相等的,都是数组首元素的地址。

  最后再讲一个字符指针,如char *p_char = "abc";这里的abc存储的位置是文字常量区,这个区域的特点就是只读,所以*p_char 是不能作为左值操作的,即不能赋值,不能改变。而普通的数组元素是储存在栈区,是可读写的。

  这里提一下sizeof()和strlen()。sizeof()和strlen()是两个完全不一样的东西,sizeof是运算符,strlen()是函数,sizeof()中()内可以是数组(计算数组空间大小),函数(计算返回值类型的空间),类型(该类型所占的空间),对象(对象实际占用的空间)和指针(指针变量的空,一般为4(32位系统)或者8(64位系统))。而strlen()函数则是专门用作计算字符床长度的函数,她是以输入的首地址开始,到‘\0‘时该字符串所占的长度,‘\0‘并不计算在内。

四、函数

  函数的本质是一个值,就是他的返回值。

  函数的形式:返回值类型 函数名(参数列表){语句列表}函数可以没有返回值,那么前面的类型就是void。函数的本质就是一个值,只是他在实现的过程中也可以进行输入输出等完成一系列的功能。主函数也是一种函数,主函数的类型是int型,在c语言中,一般主函数用return 0来表示主函数运行正常。函数是模块化编程的一种体现,利用函数可以将复杂的工程分解成许多小的功能模块,分模块化实现。 函数在使用前要先声明,并且要有相应的定义。函数的声明放在头文件中,函数的定义则在相应的函数库文件中。

  形参和实参:在定义函数时,函数的参数列表中的参数就是函数形参;调用函数时,在函数的()中放的参数就是实参。形参是局部变量,又叫临时变量,只有在函数被调用的时候才给他分配地址空间,在调用结束时候就收回,因此这个变量的生存周期就是该函数的运行周期,作用域就仅限于这个函数的范围。在函数被调用的时候,函数{}中的语句列表中的形参全部被实参替代,这就是形参和实参的关系。

  函数的返回值只能有一个或者没有。所以在需要多个数据返回的时候怎么办?这里用了一个巧妙的办法,将函数的形参定为一个指针变量,然后再调用函数的时候,将需要的参数的地址放在参数列表中,这样就可以实现对个数值返回的效果了。

Ubuntu的多文件编译以及c语言的数组、函数

标签:

原文地址:http://www.cnblogs.com/wangyouwei/p/5700620.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!