C语言入门小册子
C语言的 main()
函数与函数调用
main()
函数的作用
任何C程序都必须包含一个 main()
函数,用于存放默认执行的代码。当程序运行时,main()
函数会被自动调用。
C程序可以根据需要包含任意数量的函数,且所有函数对于其他函数都是“可见”的。例如:
/* fdomain.c */
#include <stdio.h>;
void func1( void );
void func2( void );
int main()
{
puts( "MAIN" );
func1();
func2();
}
void func1( void )
{
puts( "FUNC1" );
func2();
}
void func2( void )
{
puts( "FUNC2" );
func1();
}
在上述例子中,main()
可以调用 func1()
和 func2()
;func1()
可以调用 func2()
;而 func2()
也可以调用 func1()
。甚至 main()
也可以被其他函数调用,但很少有实际需要这样做的场景。虽然 main()
在上述代码中排在第一位,但并没有强制要求,只是按惯例 main()
通常写在文件的开头。
函数的递归调用
函数可以递归调用自身,例如:
void func1()
{
func1(); // 无限递归调用,直至栈溢出
}
函数的定义
函数的定义格式如下:
float sphere( int rad )
{
...
}
-
函数头部:
- 返回值类型:如
float
表示返回一个浮点数。 - 函数名:如
sphere
。 - 参数列表:如
(int rad)
表示函数接受一个整数参数。
- 返回值类型:如
-
函数体:
用于定义函数的逻辑。
函数原型
ANSI C 标准要求函数提供原型,以便编译器能够更好地检查函数调用。例如:
float sphere( int rad );
示例:简单的函数调用
以下是一个“发射武器”的简单程序:
/* bango.c */
#include <stdio.h>
void fire( void );
void main()
{
printf( "Firing!\n" );
fire();
printf( "Fired!\n" );
}
void fire( void )
{
printf( "BANG!\n" );
}
程序输出:
Firing!
BANG!
Fired!
fire()
函数不返回值,也不接受参数,因此其返回类型和参数都被声明为 void
。函数完成后自动返回,无需显式使用 return
。
修改:接受参数
修改后的版本让 fire()
函数接收一个参数,定义发射的次数:
/* fire.c */
#include <stdio.h>
void fire( int n );
void main()
{
printf( "Firing!\n" );
fire( 5 );
printf( "Fired!\n" );
}
void fire( int n )
{
int i;
for ( i = 1; i <= n ; ++i )
{
printf( "BANG!\n" );
}
}
程序输出:
Firing!
BANG!
BANG!
BANG!
BANG!
BANG!
Fired!
参数与参数传递
多参数
函数可以接受多个参数,用逗号分隔:
printf( "%d times %d = %d\n", a, b, a * b );
调用函数时,传递的值称为“实参”(argument),而函数中接收的变量称为“形参”(parameter)。
参数作用域
函数头部中声明的参数会作为局部变量,只在函数内部有效。例如:
fire( shots );
...
void fire( int n )
...
这里实参 shots
的值传递给形参 n
。两者可以同名,但即使同名,它们也是独立的变量。
参数顺序
参数会按照调用时的顺序传递,例如:
/* pmmatch.c */
#include <stdio.h>
void showme( int a, int b );
void main()
{
int x = 1, y = 100;
showme( x, y );
}
void showme( int a, int b )
{
printf( "a=%d b=%d\n", a, b );
}
程序输出:
a=1 b=100
参数的独立性
函数对形参的操作不会影响实参。例如:
/* noside.c */
#include <stdio.h>
void showmore( int a, int b );
void main()
{
int x = 1, y = 100;
showmore( x, y );
printf( "x=%d y=%d\n", x, y );
}
void showmore( int a, int b )
{
printf( "a=%d b=%d\n", a, b );
a = 42;
b = 666;
printf( "a=%d b=%d\n", a, b );
}
程序输出:
a=1 b=100
a=42 b=666
x=1 y=100
形参 a
和 b
的值被修改,但实参 x
和 y
的值未受影响。
数组作为参数
数组可以作为参数传递给函数:
/* fnarray.c */
#include <stdio.h>
#define SIZE 10
void testfunc( int a[] );
void main()
{
int ctr, a[SIZE];
for( ctr = 0; ctr < SIZE; ++ctr )
{
a[ctr] = ctr * ctr;
}
testfunc( a );
}
void testfunc( int a[] )
{
int n;
for( n = 0; n < SIZE; ++ n )
{
printf( "%d\n", a[n] );
}
}
程序输出数组中每个元素的值。
返回值
函数可以通过 return
返回值。返回值可以直接赋值给变量,作为参数传递给其他函数,或直接忽略。例如:
volume = sphere( radius ); // 返回值赋给变量
printf( "Volume: %f\n", sphere( radius ) ); // 返回值作为参数
一个函数可以包含多个 return
语句。例如:
if( error == 0 )
{
return( 0 );
}
else
{
return( 1 );
}
如果函数不需要返回值,则其返回类型声明为 void
:
void ftest( int somevar )
{
...
if( error == 0 )
{
return();
}
...
}
return
语句只能返回一个值,但可以返回指向数组或结构体的指针。有关指针的内容将在后续详细讨论。