zoukankan      html  css  js  c++  java
  • C语言进阶——goto 和 void 的分析08

    遭人遗弃的goto:

    • 高手潜规则:禁止使用goto
    • 项目经验:程序质量与goto的出现次数成反比
    • 最后的判决:将goto打入冷宫

    程序示例1:(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     
    14     p = (int*)malloc(sizeof(int) * n);
    15     
    16 STATUS:
    17     p[0] = n;    
    18     
    19     free(p);
    20 }
    21 
    22 int main()
    23 {  
    24     printf("begin...
    ");
    25     
    26     printf("func(1)
    ");
    27     
    28     func(1);
    29     
    30     printf("func(-1)
    ");
    31     
    32     func(-1);
    33     
    34     printf("end...
    ");
    35     
    36     return 0;
    37 }

    在函数中,从第8行到第16行本来是顺序执行的,可是当满组if条件的时候,就会破环这个程序原来的结构,导致出现错误。

    goto语句就介绍到这里,下面来讲一下void:

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

    • 如果函数没有返回值,那么就应该将其声明为void
    • 如果函数没有参数,应该声明其参数为void

    程序示例2:

     1 #include<stdio.h>
     2 
     3 f()
     4 {
     5     
     6 }
     7 
     8 int main()
     9 {
    10     int i= f(1,2,3,4);
    11     printf("%d
    ",i);
    12     return 0;
    13 }

    上面这段程序,可能会有人认为它在编译的时候会报错,其实不然:

    • 当函数没有返回值的时候,会默认返回一个int类型,也就是说你可以在这个函数里面加上一条return用于返回一个int语句,但是如果你不加的话,编译器会默认给你返回一个1。
    • 当函数的参数列表没有任何参数,且没有声明为void,默认可以接受任意多个参数

    为什莫会这样呢,因为C语言不是一种强类型的语言。

    程序示例3:

    #include<stdio.h>
    
     void f(void)
    {
        return 3;
    }
    
    int main()
    {
        int i= f(1,2,3,4);//error
        printf("%d
    ",i);
        return 0;
    }

    这段代码是将示例2中的代码稍加修改得到的,现在这段代码是不可以通过编译的。

      void的意义,有人想到,void既然是一种类型,那么我们是否可以像使用其他类型,比如说int,char 一样的使用它来创建变量呢?答案是否定的,你可以将void理解为一种抽象类型。

      不存在void普通变量(指针变量例外),C语言中没有定义void究竟是多大内存的别名,也就是说没有void标尺,无法在内存中裁剪出void对应的变量。

    小贴士:

    ANSIC:标准C语言规范

    扩展C:在ANSIC的基础上进行了扩充

    程序示例4:

    1 #include<stdio.h>
    2 
    3 int main()
    4 {
    5     printf("%d
    ",sizeof(void));
    6     return 0;
    7 }

    上面这段代码在ANSIC编译器中无法通过编译,但是对于支持GNU标准的额gcc编译器而言是合法的。(但是我们最好是按照C语言标准来学习C语言,所以我们可以认为上面这段代码是不合法的,有的编译器生产厂家认为标准C的特性不够,是自己加上去的)

    void虽然不能定义普通的变量,但是可以创建指针变量:

    • C语言规定只有相同类型的指针才可以相互赋值
    • void *  指针作为左值用于 “接受” 任意类型的指针
    • void* 指针作为右值使用时需要进行强制类型转换

    程序示例5:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 int main()
     4 {
     5     int *pi = (int *) malloc(sizeof(int));
     6     char *pc = (char *)malloc(sizeof(char));
     7     void *p=NULL;
     8     int *pni=NULL;
     9     char * pnc=NULL;
    10 
    11     p=pi; //ok
    12     pni =p; //error
    13 
    14     p=pc; //ok
    15     pnc = p;  //error
    16 
    17     return 0;
    18 }

    在标准C语言中12 和 15 行会报错,但是有的编译器会扩展C语言规范,所以上述代码在你的编译器中有可能时通过的。

    程序示例6:

    #include <stdio.h>
    
    void MemSet(void* src, int length, unsigned char n)
    {
        unsigned char* p = (unsigned char*)src;
    
        int i = 0;
    
        for(i=0; i<length; i++)
        {
            p[i] = n;
        }
    }
    
    int main()
    {
        int a[5];
        int i = 0;
    
        MemSet(a, sizeof(a), 0);
    
        for(i=0; i<5; i++)
        {
            printf("%d
    ", a[i]);
        }
    
        return 0;
    }

    MeMset这个函数用void类型的指针接受一个int(也可以接受其他类型的指针),然后将其强制转化为unsigned char 类型的指针,将其每个字节都设置为0,最后在主函数会输出 5 个0,因为每一个字节都被设置为0,所以四个为0的字节组合的一个int类型的值也是0,你也可以将他的每个自己设置为其他的数。

    小结:

    • 现代软件工程中禁止使用goto语句
    • void是一种抽象类型的数据类型
    • void类型不能用于定义变量
    • void类型用于声明函数的无参数
    • void类型用于用于声明函数的无返回值
    • 可以定义void* 类型的指针
    • void* 类型的子真可以接受任意类型的指针值
  • 相关阅读:
    创业者要有杀手气质和传教士能力
    一次只专心地做一件事,全身心地投入并积极地希望它成功
    以变应变,才有出路
    得到的并不一定就值得庆幸,失去的也并不完全是坏事情
    独处可以激发思考的力量
    把情感装入理性之盒
    随着现实的变化,我们必须随之调整自己的观念、思想、行动及目标
    岁月在变迁,彼此在成长。而我在流浪
    [TJOI 2016&HEOI 2016]排序
    [HAOI 2008]糖果传递
  • 原文地址:https://www.cnblogs.com/luojianyi/p/9216411.html
Copyright © 2011-2022 走看看