• 3.2 自定义函数


    我们不仅可以调用C标准库提供的函数,也可以定义自己的函数,事实上我们已经这么做了:我们定义了main函数。例如:

    1. int main(void)
    2. {
    3. int hour = 11;
    4. int minute = 59;
    5. printf("%d and %d hours\n", hour, minute / 60);
    6. return 0;
    7. }

    main函数的特殊之处在于执行程序时它自动被操作系统调用,操作系统就认准了main这个名字,除了名字特殊之外,main函数和别的函数没有区别。

    main函数不带任何参数,参数列表应该写成void。main函数的返回值是int型的,return 0;这个语句表示返回值是0,main函数是被操作系统调用的,通常程序执行成功就返回0,在执行过程中出错就返回一个非0值。比如我们将main函数中的return语句改为return 4;再执行它,执行结束后可以在Shell中看到它的退出状态(Exit Status)

    $ ./a.out

    11 and 0 hours

    $ echo $? //在Shell中查看main的退出状态命令

    4

    $?是Shell中的一个特殊变量,表示上一条命令的退出状态。

    关于main函数需要注意两点:

     (1)old规范中main函数不写返回值,默认返回int型。但是编译器无法检查程序中可能存在的Bug,增加了调试难度。所以main函数中必须明确写出返回值。

    (2)其实操作系统在调用main函数时是传参数的,main函数最标准的形式应该是int main(int argc, char *argv[])如果不使用系统传进来的两个参数,C标准也允许int main(void)这种写法。但除了这两种形式之外,定义main函数的其它写法都是错误的。

    我们先从不带参数也没有返回值的函数开始学习定义和使用函数:

    例 3.2. 最简单的自定义函数

    1. #include
    2. void newline(void)
    3. {
    4. printf("\n");
    5. }
    6. int main(void)
    7. {
    8. printf("First Line.\n");
    9. newline();
    10. printf("Second Line.\n");
    11. return 0;
    12. }

    函数原型(Prototype)、函数声明、函数定义概念区分:

    例 3.3. 较简单的自定义函数

    1. #include
    2. void newline(void)
    3. {
    4. printf("\n");
    5. }
    6. void threeline(void)
    7. {
    8. newline();
    9. newline();
    10. newline();
    11. }
    12. int main(void)
    13. {
    14. printf("Three lines:\n");
    15. threeline();
    16. printf("Another three lines.\n");
    17. threeline();
    18. return 0;
    19. }

    函数原型:比如void threeline(void)这一行,声明了一个函数的名字、参数类型和个数、返回值类型,这称为函数原型

    函数声明:在代码中可以单独写一个函数原型,后面加;号结束,而不写函数体,例如:

    void threeline(void);

    这种写法只能叫函数声明而不能叫函数定义,只有带函数体的声明才叫定义。

    函数定义:只有分配存储空间的变量声明才叫变量定义,其实函数也是一样,编译器只有见到函数定义才会生成指令,而指令在程序运行时当然也要占存储空间。

    如果在调用函数之前没有声明会怎么样呢?有的读者也许碰到过这种情况,我可以解释一下,但绝不推荐这种写法。比如按上面的顺序定义这三个函数,但是把开头的两行声明去掉:

    1. #include
    2. int main(void)
    3. {
    4. printf("Three lines:\n");
    5. threeline();
    6. printf("Another three lines.\n");
    7. threeline();
    8. return 0;
    9. }
    10. void newline(void)
    11. {
    12. printf("\n");
    13. }
    14. void threeline(void)
    15. {
    16. newline();
    17. newline();
    18. newline();
    19. }

    编译时会报警告:

    $ gcc main.c
    main.c:17: warning: conflicting types for ‘threeline’
    main.c:6: warning: previous implicit declaration of ‘threeline’ was here

    但仍然能编译通过,运行结果也对。这里涉及到的规则称为函数的隐式声明(Implicit Declaration),在main函数中调用threeline时并没有声明它,编译器认为此处隐式声明了int threeline(void);隐式声明的函数返回值类型都是int,由于我们调用这个函数时没有传任何参数,所以编译器认为这个隐式声明的参数类型是void,这样函数的参数和返回值类型都确定下来了,编译器根据这些信息为函数调用生成相应的指令。然后编译器接着往下看,看到threeline函数的原型是void threeline(void),和先前的隐式声明的返回值类型不符,所以报警告。好在我们也没用到这个函数的返回值,所以执行结果仍然正确。

  • 相关阅读:
    threejs(3)-详解材质与纹理
    Monaco Editor教程(十四):monaco中的位置区间Range类型的详细解释
    第八章:动态内存申请
    echarts折线图的symbol自定义样式
    【性能优化】MySQL性能优化之存储引擎调优
    【netty从入门到放弃】netty转发tcp数据到多客户端
    网络编程基础
    机器人地面站-[QGroundControl源码解析]-[1]
    IO流的字符流+对象流+打印流+内存流+随机访问流(2)
    java-php-net-python-税务申报系统ssh计算机毕业设计程序
  • 原文地址:https://blog.csdn.net/qianniuwei321/article/details/126805300