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 )
{
  ...
}
  1. 函数头部

    • 返回值类型:如 float 表示返回一个浮点数。
    • 函数名:如 sphere
    • 参数列表:如 (int rad) 表示函数接受一个整数参数。
  2. 函数体
    用于定义函数的逻辑。

函数原型

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

形参 ab 的值被修改,但实参 xy 的值未受影响。


数组作为参数

数组可以作为参数传递给函数:

/* 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 语句只能返回一个值,但可以返回指向数组或结构体的指针。有关指针的内容将在后续详细讨论。

Last modified: Monday, 27 January 2025, 10:51 PM