zoukankan      html  css  js  c++  java
  • 第8课

    第8课 - goto和void分析

    1. 遭人嫌弃的goto

    (1)高手潜规则:禁用goto

    (2)项目经验:程序质量与goto的出现次数成反比;c语言是一门结构化语言,goto会破坏C语言的结构化特性。

    (3)最后的判决:将goto打入冷宫

    【goto副作用分析】

     1 #include <stdio.h>
     2 #include <malloc.h>
     3 
     4 void func(int n)
     5 {
     6     int* p = NULL;
     7 
     8     if(  n < 0 )
     9     {
    10         goto STATUS;
    11     }
    12 
    13     p = (int*)malloc(sizeof(int) * n);  // 当 n<0 时不执行这行
    14     
    15 STATUS:
    16     p[0] = n;    // n<0 时,p为野指针,会产生段错误
    17     
    18     free(p);
    19 }
    20 
    21 int main()
    22 {  
    23     printf("begin...
    ");
    24 
    25     printf("func(1)
    ");
    26     func(1);
    27     
    28     printf("func(-1)
    ");
    29     func(-1);
    30     
    31     printf("end...
    ");
    32     
    33     return 0;
    34 }

    2. void的意义

    2.1 void修饰函数返回值和参数

    (1)void 修饰函数返回值和参数是为了表示 "无"

    (2)如果函数没有返回值,那么应该将其声明为void;否则编译器默认返回值类型为int

    (3)如果函数没有参数,应该声明其参数为void;否则编译器默认函数可以传递任意多个参数

     1 #include <stdio.h>
     2 
     3 /*
     4 // 若函数没有返回值,编译器默认返回值为int类型
     5 // 若函数没有参数,编译器默认函数可以传递任意个参数 
     6 f()    
     7 {
     8 
     9 }
    10 */
    11 
    12 void f(void)   // 函数没有返回值,不接受参数
    13 {
    14 
    15 }
    16 
    17 int main()
    18 {
    19     // int i = f(1, 2, 3);
    20 
    21     return 0;
    22 }

    2.2 不存在void变量

    C语言没有定义void究竟是多大内存的别名,因此没有void的标尺,无法在内存中裁剪出void对应的变量(void只是一种抽象的类型)。

     1 #include <stdio.h>
     2 
     3 int main()
     4 {
     5     // void var;    // error
     6     // void array[5];   // error
     7 
     8     void *pv;   // 指针要么为4字节,要么为8字节,可以定义void类型的指针变量
     9 
    10     return 0;
    11 }

    小贴士:

    ANSI C:标准C语言的规范

    扩展C:编译器厂商在ANSI C的基础上进行了扩充,像我们平时使用的gcc、VS编译器就是使用的扩展C

    【void在ANSI C和扩展C中的区别】

    1 #include <stdio.h>
    2 
    3 int main()
    4 {
    5     printf("cc sizeof(void) = %zu
    ", sizeof(void));    // 在ANSI C编译器中编译无法通过
    6                                                         // 在支持GNU标准的gcc编译器中编译通过,结果为1
    7 
    8     return 0;
    9 }

    bcc32编译器(使用ANSI C标准)  ==>   编译失败

      

    gcc编译器  ==>  编译通过

      

    2.3 void指针的意义

    (1)C语言规定只有相同类型的指针才可以相互赋值

    (2)void *指针作为左值用于接收任意类型的指针

    (3)void *指针作为右值使用时需要进行强制类型转换

         

    【通过void*实现MemSet函数】

     1 #include <stdio.h>
     2 
     3 void MemSet(void* src, int length, unsigned char n)
     4 {
     5     unsigned char* p = (unsigned char*)src;
     6     
     7     int i = 0;
     8     
     9     for(i=0; i<length; i++)
    10     {
    11         p[i] = n;
    12     }
    13 }
    14 
    15 int main()
    16 {
    17     int a[5]; // char a[5] double a[5]
    18     int i = 0;
    19     
    20     MemSet(a, sizeof(a), 0);
    21     
    22     for(i=0; i<5; i++)
    23     {
    24         printf("%d
    ", a[i]);
    25     }
    26     
    27     return 0;
    28 }
  • 相关阅读:
    http状态码
    Django基础篇(二)
    Django基础篇
    mysql进阶
    mysql数据库的基本操作
    JavaScript
    分布式原理之RPC框架
    Java实现本地缓存
    模版方法模式:封装算法 && 迭代器与组合模式:管理良好的集合
    分布式高并发系统设计与分析
  • 原文地址:https://www.cnblogs.com/shiwenjie/p/11853891.html
Copyright © 2011-2022 走看看