1、函数的定义

  • 定义
  • 函数定义在调用代码前面,就无需声明

    1. return_type function_name( parameter list )
    2. {
    3. body of the function
    4. }
  • 定义在前,调用在后

    #include <stdio.h>
    /* 函数返回两个数中较大的那个数 */
    int max(int num1, int num2)
    {
      /* 局部变量声明 */
      int result;
    
      if (num1 > num2)
          result = num1;
      else
          result = num2;
    
      return result;
    }
    int main(){
    
      int mm = max(3,9);
      printf("%d\n",mm);
    }
    
  • 事先声明 ```java int max(int num1, int num2);

int main(){

int mm = max(3,9);
printf("%d\n",mm);

}

int max(int num1, int num2) { / 局部变量声明 / int result;

if (num1 > num2)
    result = num1;
else
    result = num2;

return result;

}

<a name="mEQP1"></a>
### 2、函数参数

- 传值调用:该方法把参数的实际值复制给函数的形式参数,修改函数内的形式参数不会影响实际参数。<br />
```java
/* 函数定义 */
void swap(int x, int y)
{
    int temp;

    temp = x; /* 保存 x 的值 */
    x = y;    /* 把 y 赋值给 x */
    y = temp; /* 把 temp 赋值给 y */

    return;
}
int main ()
{
    /* 局部变量定义 */
    int a = 100;
    int b = 200;

    printf("交换前,a 的值: %d\n", a );// 100
    printf("交换前,b 的值: %d\n", b );// 200

    /* 调用函数来交换值 */
    swap(a, b);

    printf("交换后,a 的值: %d\n", a );// 100
    printf("交换后,b 的值: %d\n", b );// 200

    return 0;
}
  • 引用调用:通过指针传递方式,形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作
    ```java

    include

/ 函数定义 / void swap(int x, int y) { int temp;

temp = *x; /* 保存 x 的值 */
*x = *y;    /* 把 y 赋值给 x */
*y = temp; /* 把 temp 赋值给 y */

return;

} int main () { / 局部变量定义 / int a = 100; int b = 200;

printf("交换前,a 的值: %d\n", a );//100
printf("交换前,b 的值: %d\n", b );//200

/* 调用函数来交换值 */
swap(&a, &b);

printf("交换后,a 的值: %d\n", a );//200
printf("交换后,b 的值: %d\n", b );//100

return 0;

}

<a name="Pkqzr"></a>
### 3、函数返回值

- 返回普通类型
```java
int getMax()
{
    return 10;
}

int main ()
{
    int a = getMax();
    printf("%d\n",a);
    return 0;
}

4、局部变量

普通局部变量

  • 局部变量:在某个函数或块的内部声明的变量称为局部变量
  • 函数的参数,形式参数,被当作该函数内的局部变量,如果与全局变量同名,局部变量会优先使用

    #include <stdio.h>
    int main ()
    {
      /* 局部变量声明 */
      int a, b;
      int c;
    
      /* 实际初始化 */
      a = 10;
      b = 20;
      c = a + b;
    
      printf ("value of a = %d, b = %d and c = %d\n", a, b, c);
    
      return 0;
    }
    

    静态局部变量

  • 希望局部变量在函数调用完毕不消失,还是上次调用的值,但是其他函数不能被引用

  • 静态局部变量,编译时赋值,只赋值一次 ```java int test(); int main(){ printf(“%d\n”,test());// 11 printf(“%d\n”,test());// 12

    return 0; }

int test() { static int c = 10; c = c + 1; return c; }

<a name="1RG5d"></a>
#### 静态局部变量 VS 普通局部变量
> 1、static局部变量只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在。
> 2、普通局部变量,只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。
> 3、静态局部变量在静态存储区分配空间,局部变量在栈里分配空间。

<a name="hQViF"></a>
#### 复合语句内的局部变量
>     **if** (1) {
>         **int** c = 20;
>     }
>     // 找不到c
>     printf("%d",c);

<a name="GZoSU"></a>
### 5、全局变量

- 全局变量:全局变量是定义在函数外部,通常是在程序的顶部。
- 全局变量在整个程序生命周期内都是有效的,在任意的函数内部能访问全局变量
<a name="HmfTo"></a>
#### 普通全局变量
```java
int g = 20;
int main ()
{
    /* 局部变量声明 */
    int g = 10;

    printf ("value of g = %d\n",  g);

    return 0;
}

静态全局变量

*****************hello.c*****************
#include <stdio.h>
#include "max.c"

// 静态全局变量
// static int b = 10; 
// 全局变量
int b = 44; // 加上static就会报错

// 全局函数也有这个问题加上static就会报错
void test(){
    printf("test\n");
}

int main(void)
{
    max();
    return 0;
}

*****************max.c*****************

/*外部变量声明*/
extern b;
void max()
{
    test();
    printf("%d\n",b);
}

静态全局变量 VS 普通全局变量

  • static全局变量编译是初始化,在main()函数之前初始化并且仅初始化一次;
  • static全局变量限定了作用范围,仅在定义该变量的源文件中有效,由于静态全局变量的作用域局限于一个源文件内,即文件作用域,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误
  • 普通全局变量可以跨越多个源文件有效,当然,其他不包含普通全局变量定义的源文件需要用extern关键字再次声明这个全局变量

    6、全局变量、局部变量区别

  • 当局部变量被定义时,系统不会对其初始化,您必须自行对其初始化;定义全局变量时,系统会自动对其初始化

  • 全局变量、静态全局变量以及静态局部变量都会被放在程序的静态数据存储区(全局可见)中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它们与堆变量、堆变量的区别。
  • 而普通局部变量在栈里分配空间
  • 从以上分析可以看出,把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。
  • 把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。

7、register

  • 变量放在寄存器中,速度比放在内存中还快

    register int c = 10;
    

    8、内部函数、外部函数

  • 普通函数的定义和声明默认情况下是extern的

  • 静态函数只是在声明他的文件当中可见,不能被其他文件所用。好处:
  • 其他文件中可以定义相同名字的函数,不会发生冲突
  • static修饰的函数只能被本文件使用

    static int power(int num, int n){
      int i , y = 1;
      for (i = 1; i <= n; i++) {
          y=y*num;
      }
      return y;
    }
    
  • extern修饰的函数可以被其他文件使用

    extern int power(int num, int n){
      int i , y = 1;
      for (i = 1; i <= n; i++) {
          y=y*num;
      }
      return y;
    }