零基础入门学习C语言008讲:函数(6)

版权声明:转载请标明出处 https://blog.csdn.net/qq_41556318/article/details/89716109

进阶:在多文件的程序中声明外部变量

在前面的课程中,我们见过的所有的程序都是在一个C程序文件中实现的,但是,我们在开发中遇到的各种各样的程序,很多都是由多个程序文件组成的,每个文件基本上就是实现了程序的部分功能,然后再把各个功能凑合起来,所以,我们现在要学着把一个文件拆成多个文件。

这是我们第一次把一个程序拆成多个文件!

请看实战演练:

file1.c(文件1)

#include <stdio.h>

int A;                     /*定义外部变量*/

void main()                          
{
      int power(int);          /*函数声明*/
      int b = 3, c, result, m;

      printf("enter the number A and its power m:\n");
      scanf("%d %d", &A, &m);
      
      c = A * b;
      printf("%d * %d = %d\n", A, b, c);

      result = power(m);
      printf("%d ^ %d = %d\n", A, m, result);
}

file2.c(文件2)

extern  A; /*声明A为一个已定义的外部变量*/

int power(int n) 
{
      int i, y = 1;

      for(i=1; i <= n; i++)
      {
            y *= A;
      }

      return y;
}

我们把这两个文件分别编译一下,都编译通过了,然后,我们点击运行,也是可以运行的。

8.9.6 用static声明外部变量

有时在程序设计中希望某些外部变量只限于被本文件使用,而不能被其它文件引用。这时就可以在定义外部变量时加一个static声明。

小改刚才的程序:

file1.c(文件1)

#include <stdio.h>

static int A;                     /*这里我们增加了static不让别的文件引用*/

void main()
{
	int power(int);          /*函数声明*/
	int b = 3, c, d, m;

	printf("enter the number a and its power m:\n");
	scanf("%d %d", &A, &m);

	c = A * b;
	printf("%d * %d = %d\n", A, b, c);

	d = power(m);
	printf("%d ^ %d = %d\n", A, m, d);
}

file2.c(文件2)

extern  A; /*声明A为一个已定义的外部变量*/

int power(int n) 
{
      int i, y = 1;

      for(i=1; i <= n; i++)
      {
            y *= A;
      }

      return y;
}

编译还是没有问题,但是运行就会报错:

static声明除了使一个局部变量变成一个静态变量之外,还能使一个全局变量捆绑在一个固定的文件里面。

8.9.7 辨析:关于变量的声明和定义

对变量而言,声明与定义的关系稍微复杂一些。在声明部分出现的变量有两种情况:一种是需要建立存储空间的(如:int a;),另一种是不需要建立存储空间的(如:extern a;)。

前者称为“定义性声明”(define declaration),或简称定义(definition)。

后者称为“引用性声明”(referencing declaration)。

广义地说,声明包括定义,但并非所有的声明都是定义。

对 “int a;” 而言,它既是声明,又是定义。而对于 “extern a;” 而言,它是声明而不是定义。

一般为了叙述方便,把建立存储空间的声明称为定义,而把不需要建立存储空间的声明称为声明。显然这里指的声明是狭义的,即非定义性声明。

例如:

void main ()

{

           extern  A;       //是声明不是定义。声明A是一个已定义的外部变量

          ..........

}

int A;       //是定义也是声明

存储类别归纳

我们试着从不同角度做些归纳:

(1)从作用于角度分,有局部变量和全局变量。它们采用的存储类别如下:

局部变量

自动变量,即动态局部变量(离开函数,值就消失)

静态局部变量(离开函数,值仍保留)

寄存器变量(离开函数,值就消失)

(形式参数可以定义为自动变量或寄存器变量)

全局变量

静态外部变量(只限本文件使用)

外部变量(即非静态的外部变量,允许其他文件引用)

(2)从变量存在的时间(生存期)来区分,有动态存储和静态存储两种类型。静态存储是程序整个运行时间都存在,而动态存储则是在调用函数时临时分配单元。

动态存储

自动变量(本函数内有效)

寄存器变量(本函数内有效)

形式参数(本函数内有效)

静态存储

静态局部变量(函数内有效)

静态外部变量(在文件内有效)

外部变量(其他文件可引用)

(3)从变量值存放的位置来区分,可分为:

内存中静态存储区

静态局部变量(函数内有效)

静态外部变量(函数外部静态变量)

外部变量(其他文件可引用)

内存中动态存储区 自动变量和形式参数
CPU中的寄存器 寄存器变量

(4)关于作用域和生存期的概念

从前面的叙述可以知道,对一个变量的性质可以从两个方面分析:一是变量的作用域,一是变量值存在时间的长短,即生存期。

前者是从空间的角度,后者是从时间的角度,二者有联系但是不是一回事。

(5)static对局部变量和全局变量的作用不同。

对局部变量来说,它使变量由动态存储方式改变为静态存储方式。而对全局变量来说,它使变量局部化(局部于本文件),但仍是静态存储方式。

从作用域角度看,凡有static声明的,其作用域都是局部的,或者是局限于本函数内(静态局部变量),或者局限于本文件内(静态外部变量)。

8.10 内部函数和外部函数

函数本质上是全局的,因为一个函数要被另外的函数调用,但是,也可以指定函数不能被其他文件调用。

我们根据函数能否被其她源文件调用,将函数区分为内部函数和外部函数。

内部函数

如果一个函数只能被本文件中其他函数所调用,它成为内部函数。

在定义内部函数时,在函数名和函数类型的前面加static

即:static 类型标识符 函数名(形参表)

如:static int fun(int a,int b)

外部函数

(1)在定义函数时,如果在函数首部的最左端加关键字extern,则表示此函数是外部函数,可供其他文件调用。如函数首部可以写为 

extern int fun(int a,int b)

这样,函数fun就可以为其他文件调用。C语言规定,如果在定义函数时省略extern,则隐含为外部函数。前面所用的函数都是外部函数。

(2)在需要调用此函数的文件中,用extern对函数作声明,表示该函数是在其他文件中定义的外部函数。

实战演练:

有一个字符串,内有若干个字符,要求输入一个字符,程序便将字符串中该字符删去。要求用外部函数实现。

file1.c

#include <stdio.h>

void main()
{
	extern void enter_string(char str[]);
	extern void delete_string(char str[], char ch);
	extern void print_string(char str[]);
	/*以上3行声明在本函数中将要调用的在其他文件中定义的3个函数*/

	char c;
	char str[80];

	enter_string(str);
	scanf("%c", &c);
	delete_string(str, c);
	print_string(str);
}

file2.c

#include <stdio.h>

//定义外部函数enter_string()

void enter_string(char str[80])
{
	gets(str);   /*向字符数组输入字符串*/
}

file3.c


/*定义外部函数 delete_string() */

void delete_string(char str[], char ch)
{
	int i, j;

	for (i = j = 0; str[i] != '\0'; i++)
	{
		if (str[i] != ch)
		{
			str[j++] = str[i];
		}
	}
	str[j] = '\0';
}

file4.c

#include <stdio.h>

void print_string(char str[])
{
	printf("%s\n", str);
}

猜你喜欢

转载自blog.csdn.net/qq_41556318/article/details/89716109