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

一、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语言的数组、函数的更多相关文章

  1. iOS开发环境C语言基础 数组 函数

    1 求数组元素的最大值 1.1 问题 创建程序,实现查询数组中最大值的功能,需求为:创建一个长度为10的数组,数组内放置10个0~99之间(包含0,包含99)的随机数作为数组内容,要求查询出数组中的最 ...

  2. C语言-------多文件编译

    (1)前段时间,学长讲解宏的一些知识  也提起了那个多文件编译,同过看别人的博客,自己也懂了一些,现在来总结一下这个多文件编译,其实和java里面的那个class的调用好像有联系 其定义即可以理解成: ...

  3. C语言include预处理命令与多文件编译

    #include预处理命令几乎使我们在第一次接触C的时候就会碰到的预处理命令,可我现在还不怎么清楚,这次争取一次搞懂. 一.#include预处理指令的基本使用 预处理指令可以将别处的源代码内容插入到 ...

  4. Ubuntu下使用gcc编译c文件,未识别cos,sin

    Ubuntu下使用gcc编译c文件,虽然我调用了math.h的头文件,但是未识别cos,sin 报错:( fft.c ) /tmp/ccwXjD8C.o: In function `fft': fft ...

  5. C文件编译、链接指令

    通过mac终端 输入指令: cc -c 文件名.c 可以把C文件编译成.o文件(其实是2进制文件) 然后通过指令 cc 文件名.o 把.o文件链接C文件所需要的C语言的底层库,成为可以直接运行的lin ...

  6. 最短的可通过编译的C语言程序

    要求:写一个最短的,能通过编译的C语言程序,但不要求能正确运行. 一般人首先想到的是除0.即 int main() { /; } 除0会引发SIGFPE信号(浮点异常). 我们也可以删掉return, ...

  7. [转]嵌入式SQC文件编译

      Src Url:http://blog.csdn.net/cws1214/article/details/12996351   A.预编译部分  1.预编译DB2篇 1.1 什么是DB2预编译 在 ...

  8. ubuntu下使用反编译apk,工具dex2jar和jd-gui

    ubuntu下使用反编译apk, 工具 1:通过apk-tool反编译出资源文件: http://code.google.com/p/android-apktool/ 2.首先使用dex2jar反编译 ...

  9. 添加Ubuntu的库文件路径

    添加Ubuntu的库文件路径 http://blog.csdn.net/r91987/article/details/6879062 关于ubuntu添加共享库路径: 1. 将绝对路径写入 /etc/ ...

随机推荐

  1. 文件上传(excel服务端解析)

    1,html结构 <!-- 引入jQuery和jQuery.form.js插件 --><script type="text/javascript" src=&qu ...

  2. php7 httpd 2.4 编译

    1.获取源码httpd-2.4.23.tar.gz   php-7.1.0.tar.gz,安装顺序必须是先安装http然后php,lnmp同理   2.安装编译环境和php.httpd依赖包,红色字体 ...

  3. 【cpp】Vector

    这vector 很有用 // compile with: /EHsc #include <vector> #include <iostream> int main() { us ...

  4. 用C++画心(转)

    原地址https://www.zhihu.com/topic/19613730/top-answers 首先上一个动态的心 代码如下: #include <stdio.h> #includ ...

  5. js倒计时跳转页面

    var t=10; setInterval(function refer(){ if(t>0){ document.getElementById("em").innerHTM ...

  6. n进制转化成十进制

    一个字节是8位二进制. 我的天啊.我发现char特别厉害: char类型能够输入整形常量.不能超过-128~127. 只能是整数类型,且范围一般不能超出-128~127.超出会溢出的.

  7. 摸索Tableau

    将本年度第几周转变为对应范围内的某日期 201607 → 2016-02-18 DATEADD('day',7*(int(RIGHT([WEEK_ID],2))-1),DATEPARSE(" ...

  8. Java中sql语句的引号问题

    1..sql语句 在数据库中,当我们查询语句时,会使用类似的语句: Select * from userinfo where userid='1' or 1; Select * from userin ...

  9. ios基础篇(二十四)—— 文字、图片的绘制及其自定义Button

    这篇文章我们主要来拿官方的控件来研究一下,我们来仿照官方的控件,自己来实现它提供的控件: 首先来看看基本的图片与文字的绘制,很简单. 一.imageView 所有的视图都是继承自UIView,所以我们 ...

  10. css中的一些概念

    1.伪类与伪元素 1.单冒号(:)用于 CSS3 伪类,双冒号(::)用于 CSS3 伪元素. 2.对于 CSS2 中已经有的伪元素,例如 :before,单冒号和双冒号的写法 ::before 作用 ...