【C语言基础】函数与变量

函数的分类:

  • 从定义角度分:
    • 库函数:随C语言编译器提供的。无须用户定义,只需在程序前包含含有该函数原型的头文件。
    • 自定义函数:用户自己定义的函数。
  • 从函数返回结果角度分:
    • 有返回值函数:函数在执行完需要返回一个值,这个值就是函数的值。
    • 无返回值函数:函数只执行任务,不返回任何值。用户在定义时可指定此类函数的返回值 为“空类型”,即void。
  • 从函数调用时的数据传递角度分:
    • 有参函数:主调函数和被调函数之间有数据的传递。
    • 无参函数:主调函数和被调函数之间不进行数据传递。无参函数通常用来执行指定操作。

每个程序有且只有一个main函数。main函数可以调用其它函数,但main函数是不能被调用的。

1 函数的定义与声明

一般形式:

返回值类型 函数名(参数列表)
{
    函数体
}

例子:

#include <stdio.h>
void iCompare(int Num1, int Num2);

int Add(int Num1, int Num2)
{
	int sum;
	sum = Num1 + Num2;
	return sum;
}

main()
{
	int a, b, sum;
	a = 10;
	b = 20;
	sum = Add(a, b);
	printf("%d + %d = %d\n", a, b, sum);

	iCompare(a, b);
}

void iCompare(int Num1, int Num2)
{

	if (Num1 > Num2)
		printf("%d > %d\n", Num1, Num2);
	else if (Num1 == Num2)
		printf("%d = %d\n", Num1, Num2);
	else
		printf("%d < %d\n", Num1, Num2);
}

运行结果:

  • 无参函数没有参数列表;
  • 若自定义函数在调用函数之后定义,需要先进行声明才可使用。上例中,iCompare函数被定义在main函数之后,因此在程序开头的第2行进行了声明:void iCompare(int Num1, int Num2); 
  • 若自定义函数在调用函数之前定义,无须进行声明。
  • 函数的定义是互相平行且独立的,所以不可以在函数中嵌套定义另一个函数,即使是在main函数中也不可以。

声明一个函数:

  • 函数的声明格式必须与该函数定义的函数头保持一致。
  • 必须以分号";"作为语句的结尾。

定义与声明的区别:

  • 定义:是在编译器里创建一个对象,为这个对象分配一块内存,并给对象取一个名字,取的名字就是变量名或对象名。这里为对象分配内存。
  • 声明:告诉编译器这个名字已经分配到一块内存了,并且这个名字现在归此声明所用,别的地方不允许再使用这个名字。这里没有为对象分配内存。

2 函数的参数

  1. 定义或声明函数时,函数参数为形式参数,即形参;
  2. 调用函数时,函数参数为实际参数,即实参。实参可以是常量、变量、表达式和函数等。

数组也可作为函数参数:

  • 可使用数组元素作为函数参数;
  • 可使用数组名作为函数。

例子:

#include <stdio.h>
void ShowArrayMember(int iMember);
void ShowArray(int iArray[]);
void EvaluateArray(int iArray[10]);

main()
{
	int iArray[10] = { 1,2,3,4,5 };
	ShowArray(iArray);

	EvaluateArray(iArray);
	ShowArray(iArray);
	for (int i = 0; i < 10; i++)
		ShowArrayMember(iArray[i]);
}

void ShowArrayMember(int iMember)
{
	printf("Current array member is: %d\n", iMember);
}

void ShowArray(int iArray[])
{
	printf("Current array members are:\n");
	for (int i = 0; i < 10; i++)
		printf("%d ", iArray[i]);
	printf("\n");
}

void EvaluateArray(int iArray[10])
{
	printf("Evaluate array...\n");
	for (int i = 0; i < 10; i++)
		iArray[i] = iArray[i] + 10*i;
}

运行结果:

3 变量与变量的存储

3.1 局部变量与全局变量

局部变量与全局变量
变量类型说                              明
局部变量在函数内部定义的变量。无法被别的函数使用。
全局变量在所有函数外部定义的变量。属于整个源文件,可以在程序中的任何位置进行访问。如果外部文件要进行调用,需要使用extern进行引用。

3.2 变量的存储

变量的存储类别有两种形式:静态存储和动态存储。可以通过存储类修饰符来告诉编译器要处理什么样的类型变量,具体有:自动(auto),静态(static),寄存器(register),外部(extern)。

3.2.1 静态存储与动态存储

从变量的产生时间上可以分为静态存储和动态存储。静态存储是指程序运行时分配固定的存储方式;动态存储是在程序运行期间根据需要进行动态的分配存储空间。

内存中,系统提供给用户的存储空间分为三部分:程序区,静态存储区,动态存储区。程序区用来存放用户要执行的程序段,数据分别放在静态存储区和动态存储区中。

  • 静态存储区:储存全局变量。全局变量从程序执行时开始分配存储单元,占据固定的内存空间,直到程序终止时,才释放其所占的存储单元。
  • 动态存储区:在调用函数时,其局部变量也被保存到动态存储区中,分配内存空间,当函数结束执行,返回到主调函数时,,该变量所占用的空间将被释放,此时局部变量也将消失。对于形参函数,只有在调用该函数时才能为形参分配内存空间,调用完成后会将所有的空间释放。

3.2.2 auto变量

函数内凡未加存储类型说明的变量均视为自动变量,也就是说自动变量可以省略说明符auto。所以,以下两种变量定义是等价的:

{
    int a, b;
    ...
}
{
    auto int a, b;
    ...
}

自动变量属于动态存储方式。

3.2.3 static变量

3.2.3.1 静态局部变量
  • 在函数内定义,属于静态存储类别。它的生存期是整个源程序。
  • 静态局部变量的作用域与自动变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后,虽然该变量还存在,但不能使用它,如果再次调用定义它的函数,又可继续使用。
  • 对于基本类型的静态局部变量,如果在说明时没有赋以初值,则系统自动赋予0值。而对于自动变量,如果不赋初值,那么它的值是不确定的。

例子:

#include <stdio.h>
int AddStatic(int x)
{
	static int i = 0;
	i += x;
	return i;
}

int AddAuto(int x)
{
	int i = 0;
	i += x;
	return i;
}

main()
{
	int i, StaticSum, AutoSum;
	for (int i = 1; i < 10; i++)
	{
		StaticSum = AddStatic(i);
		AutoSum = AddAuto(i);
		printf("%d: StaticSum = %d, AutoSum = %d\n", i, StaticSum, AutoSum);
	}
}

运行结果:

3.2.3.2 静态全局变量

非静态全局变量与静态全局变量在存储方式上是相同的,但作用域是不同的。非静态全局变量的作用域是整个源程序,而静态全局变量的作用域是该变量的源文件,在同一源程序的其它源文件中不能使用它。

3.2.4 register变量

寄存器变量允许将局部变量的值存放在CPU中的寄存器中,使用时不需要访问内存,而直接从寄存器中读写。寄存器变量的说明符是register。

  • 用户无法获得寄存器变量的地址。
  • 如果想要有效地利用register关键字,必须像汇编语言程序员那样了解处理器的内部结构,知道可用于存放变量的寄存器的数量、种类和工作方式。对于这些细节,不同计算机可能是不同的。因此,对于一个要具备可移植性的程序来说,register的作用是不大的。

3.2.5 extern变量

当一个源文件中的函数想引用其它源文件中的变量,就可以用extern来声明外部变量。声明格式:

extern 数据类型 外部变量表;

  • 在函数内的extern变量声明,表示引用本源文件中的外部变量;
  • 在函数外的extern变量声明(通常在文件开头),表示引用其它文件中的外部变量。

如果外部变量不在文件的开头定义,其有效的作用范围只限于定义到文件结束处。

4 内部函数与外部函数

函数是C语言程序中的最小单位,通常把一个或多个函数保存为一个文件,这个文件称为源文件。定义一个函数,这个函数就要被另外的函数所调用。但当一个源程序由多个源文件组成时,可以指定函数不能被其它文件调用。

内部函数与外部函数
函数类型说                                 明
内部函数

又称为静态函数。只能被所在的源文件所使用,不能被其它文件调用。

定义时,只需在函数返回值类型前加上关键字static即可,格式如下:

static 返回值类型 函数名(参数列表)

好处:不同的开发者可以分别编写不同的函数,而不必担心所使用的函数是否会与其它源文件中的函数同名。

外部函数

外部函数是可以被其它源文件调用的函数。

定义时,使用关键字extern进行修饰,extern关键字可以省略;

使用时,需要先用关键字extern声明所用的函数是外部函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值