1、 常量
常量指定的是在软件编程过程中不能给赋值且值不能被改变的量。一般包括数字、字符、字符串常量等。
例如:整型常量:12、0、-3;
实型常量:4.6、-1.23;
字符常量:‘a’、‘b’。
标识符:用来标识变量名、符号常量名、函数名、数组名、类型名、文件名的有效字符序列。
符号常量:用标示符代表一个常量。在C语言中,可以用一个标识符来表示一个常量,称之为符号常量。
符号常量在使用之前必须先定义,其一般形式为:
#define 标识符 常量
其中#define也是一条预处理命令(预处理命令都以"#"开头),称为宏定义命令(在后面预处理程序中将进一步介绍),其功能是把该标识符定义为其后的常量值。一经定义,以后在程序中所有出现该标识符的地方均代之以该常量值。
2、 变量
顾名思义就是在程序运行的时候可以给变的量称为变量,变量一般是我们在编写程序的时候自己定义的。
定义方式如下:
变量类型 变量名;
变量类型指的是定义的变量的类型,一般变量的类型包括基本数据类型、指针类型、复杂类型等。
变量名表示的是定义的变量的名称。
一个变量应该有一个名字,在内存中占据一定的存储单元。变量定义必须放在变量使用之前。一般放在函数体的开头部分。要区分变量名和变量值是两个不同的概念。
例如:
int a;//表示定义一个int 型的变量a。
a = 100;//表示对变量a的值进行给变,将其赋值为100.
通过这两个语句我们就定义了一个变量a,变量a的值为100.
其他类型的变量:
char b;//char型变量b
float c;//定义一个float类型的变量c
变量根据作用域的不同分为全局变量和局部变量,全局变量也称为外部变量,它是在函数外部定义的变量。它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序。 局部变量也称为内部变量。局部变量是在函数内作定义说明的。其作用域仅限于函数内, 离开该函数后再使用这种变量是非法的。
变量类型 | 变量范围 |
局部变量 | 局部变量的作用域是作用域是自变量定义到当前函数体结束。 |
全部变量 | 整个函数 |
我们定义的变量都有一个生命周期和作用域,一般不同方式定义的变量的生命周期和作用域不一样。
作用域指定但是变量的使用范围,不同的作用域可以定义相同名的变量。使用的时候有限使用离得最近的变量。不同作用域的相同名称的变量不会相互影响。
生命周期指的是一个变量从创建到销毁的时间,称为生命周期。
变量的定义形式 | 作用域 | 生命周期 | ||
局部变量 | static修饰的局部变量 | 一对{}内({}称为一个函数体) | 整个程序运行期间 | |
普通的局部变量 | 一对{}内 ({}称为一个函数体) | 从变量的定义到当前函数运行完成 | ||
全局变量 | static修饰的全局变形量 | 当前文件可以使用,其他文件使用extern声明也不能调用 | 整个函数运行期间 | |
普通的全局变量 | 整个项目可以使用(非当前文件需要使用extern声明) | 整个函数运行期间 | ||
extern声明的变量 | 整个项目文件都可以使用 | 整个程序运行期间 | ||
extern声明函数 | 整个程序 | 整个程序运行期间 | ||
static修饰函数 | 当前文件 | 整个程序运行期间 |
需要注意的是static修饰的局部变量只能初始化一次,但是可以进行多次赋值。
变量数据类型的转换
变量在传递值的过程中,有可能会在不同数据类型之间传递,这样的话就需要对数据类型进行转换。数据类型的转换方式有两种。
1)隐式转换也称做自动转换(数据类型所占字节小于要转数据类型)
例如:
char ch = 'c';
int a = ch;//这是将一个char类型的数据复制个一个int型的数据,这属于隐式转换
double b = a;//将int型的a数据转化为double类型
2)强制转换(大转小),强制转换的时候,一定要在转换的变量之前增加强制转换的数据类型。如一下例子需要在a变量之前增加char类型强制转换
例如:
int a = 100;
char c = (char)a;//这是将一个int型的数据强制转换成char型,超出char型的数据将会丢失
3、 函数
1)函数的概念
函数指的是一个程序的集合,专门用于实现某一个功能的代码块。在程序的编写中使用函数可以提高代码的可阅读性和增加代码的可维护性。
从函数定义的角度看,函数可分为库函数和用户定义函数两种。库函数:由C系统提供,用户无须定义,也不必在程序中作类型说明,只需在程序前包含有该函数原型的头文件即可在程序中直接调用。用户定义函数:由用户按需要写的函数。对于用户自定义函数,不仅要在程序中定义函数本身,而且在主调函数模块中还必须对该被调函数进行类型说明,然后才能使用。
根据函数的返回值和函数有无参数可以分为以下四种函数的形式。有参无返、有参有返、无参无返和无参有返。
2)函数的定义
定义函数需要注意两个方面,那就是函数的返回类型和函数参数的类型。我们所能定义和使用的变量类型都可以作为函数的返回值和函数参数的类型。
例如:int、 float 、double、 long 、 数组、 结构体和枚举等多可以作为函数的返回值和参数。后面会陆续介绍。
1 无参有返函数的定义形式
类型标识符 函数名()
{
声明部分
语句
}
其中类型标识符和函数名称为函数头。类型标识符指明了本函数的类型,函数的类型实际上是函数返回值的类型。 该类型标识符与前面介绍的各种说明符相同。函数名是由用户定义的标识符,函数名后有一个空括号,其中无参数,但括号不可少。{}中的内容称为函数体。在函数体中声明部分,是对函数体内部所用到的变量的类型说明。
函数参数一般是通过return返回的。
例如:
int fun()
{
函数体;
return 1;
}
此例子表示定义了一个有返无参的函数,返回值为int类型。
2 有返有参函数定义的一般形式
类型标识符 函数名(形式参数表列)
{
声明部分
语句
}
其中类型标识符和函数名称为函数头。类型标识符指明了本函数的类型,函数的类型实际上是函数返回值的类型。 该类型标识符与前面介绍的各种说明符相同。函数名是由用户定义的标识符,函数名后有一个括号。括号中的形式参数列表就是需要传递的参数{}中的内容称为函数体。在函数体中声明部分,是对函数体内部所用到的变量的类型说明。
例如:
int fun( int a,int b)
{
函数体;
return 1;
}
此例子表示定义了一个有返有参的函数,返回值为int类型。参数列表为int a,int b。a和b的值是传递到函数中取的。
3 无返有参函数定义的一般形式
void 函数名(形式参数表列)
{
声明部分
语句
}
其中void 标识符指明了本函数的类型,本函数是一个返回为空类型的函数,因此本函数是没有返回指的。函数名是由用户定义的标识符,函数名后有一个空括号。其中无参数,但括号不可少。{}中的内容称为函数体。在函数体中声明部分,是对函数体内部所用到的变量的类型说明。
例如:
void fun( int a,int b)
{
函数体;
}
此例子表示定义了一个无返返有参的函数,返回值为void类型。参数列表为int a,int b。a和b的值是传递到函数中取的。
4 无返无参函数定义的一般形式
void 函数名()
{
声明部分
语句
}
其中void 标识符指明了本函数的类型,本函数是一个返回为空类型的函数,因此本函数是没有返回指的。函数名是由用户定义的标识符,函数名后有一个空括号。其中无参数,但括号不可少。{}中的内容称为函数体。在函数体中声明部分,是对函数体内部所用到的变量的类型说明。这种函数一般用于对一些器件或者堆空进行初始化使用。
例如:
void fun()
{
函数体;
}
此例子表示定义了一个无返返有参的函数,返回值为void类型。
需要注意的是如果调用的函数是有返函数,那么在函数体中必须要有一个return语句返回返回值。
3)函数的调用
在程序中是通过对函数的调用来执行函数体,其过程与其它语言的子程序调用相似。
函数调用的一般形式为:
函数名(实际参数表);
对无参函数调用时则无实际参数表。实际参数表中的参数可以是常数,变量或其它构造类型数据及表达式。各实参之间用逗号分隔。
在主调函数中调用某函数之前应对该被调函数进行说明(声明),这与使用变量之前要先进行变量说明是一样的。在主调函数中对被调函数作说明的目的是使编译系统知道被调函数返回值的类型,以便在主调函数中按此种类型对返回值作相应的处理。
其一般形式为:
类型说明符 被调函数名(类型 形参,类型 形参…);
或为:
类型说明符 被调函数名(类型,类型…);
括号内给出了形参的类型和形参名,或只给出形参类型。这便于编译系统进行检错,以防止可能出现的错误。
例: main函数中对max函数的说明为:
int max(int a,int b);
或写为:
int max(int,int);
但是有以下几个情况需要对函数进行声明:
A、如果被调函数的返回值是整型或字符型时,可以不对被调函数作说明,而直接调用。这时系统将自动对被调函数返回值按整型处理。
B、当被调函数的函数定义出现在主调函数之前时,在主调函数中也可以不对被调函数再作说明而直接调用。
C、如在所有函数定义之前,在函数外预先说明了各个函数的类型,则在以后的各主调函数中,可不再对被调函数作说明。
在C语言中,可以用以下几种方式调用函数:
A、函数直接作为表达式进行调用,这种函数一般都是针对有返回值的函数的一种调用方式。例如 :int a = fun(a,b);fun函数是一个有返回值的函数,返回值为int类型。
B、函数语句是直接将调用的函数当成一个语句进行适应,这种方式是用于没有返回值的函数。例如:fun(a,b);fun函数是一个没有返回值的函数。
C、函数也可以当做另一个函数的实参进行使用。但是这种调用方式和第一种一样都是针对有返回值的函数进行调用的。例如:fun(fun1(a,b),c);fun1是一个又返回值的函数。
D、对库函数的调用不需要再作说明,但必须把该函数的头文件用include命令包含在源文件前部。
4)函数嵌套调用函数
C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级函数和下一级函数的问题。但是C语言允许在一个函数的定义中出现对另一个函数的调用。这样就出现了函数的嵌套调用。即在被调函数中又调用其它函数
例如:
fun()
{
……
fun1(a,b);//调用函数fun1
……
}
fun1(int a,int b)
{
……
fun2();//调用函数fun2
……
}
fun2()
{
函数体;
}
以上例子就是一个函数嵌套调用的例子,首先函数fun()调用fun1(int a,int b)函数。而fun1(int a,int b)函数有调用fun2()函数。
4)函数递归调用函数
一个函数在它的函数体内调用它自身称为递归调用。这种函数称为递归函数。C语言允许函数的递归调用。在递归调用中,主调函数又是被调函数。执行递归函数将反复调用其自身,每调用一次就进入新的一层。
例如有函数f如下:
int fun(int x)
{
int y;
z=fun(y);//递归调用函数
return z;
}
这个函数是一个递归函数。但是运行该函数将无休止地调用其自身,这当然是不正确的。为了防止递归调用无终止地进行,必须在函数内有终止递归调用的手段。常用的办法是加条件判断,满足某种条件后就不再作递归调用,然后逐层返回。下面举例说明递归调用的执行过程。
需要注意的是如果使用递归调用函数,如果没有函数出口,那么可能会造成内存的溢出导致软件崩溃。