天天看點

第8課 goto 和 void 分析

1. 遭人遺棄的goto

(1)高手潛規則:禁用goto

(2)項目經驗:程式品質與goto出現的次數成反比

(3)最後的判決:将goto打入冷宮(1)循環語句的基本工作方式

【執行個體分析】goto副作用的分析

#include <stdio.h>
#include <malloc.h>

void func(int n)
{
    int* p = NULL;

    if(  n < 0 )
    {
        goto STATUS;
    }

    
    p = (int*)malloc(sizeof(int) * n);//n<0時,将不被執行
    
STATUS:
    p[0] = n;    //n<0時,p記憶體未申請,出現錯誤
    
    free(p);
}

int main()
{  
    printf("begin...\n");
    
    printf("func(1)\n");
    
    func(1);
    
    printf("func(-1)\n");
    
    func(-1);
    
    printf("end...\n");
    
    return 0;
}      

2. void的意義

(1)void修飾函數傳回值和參數——為了表示“無”

  ①如果函數沒有傳回值,那麼應該将其聲明為void

  ②如果函數沒有參數,應該聲明其參數為void

任意參數 無參(用void聲明)
#include<stdio.h>

f() //f()函數任意參數,傳回值預設int型
{

}

int main()
{
  int i=f(1,2,3)

  return 0;

}      
#include<stdio.h>

void f(void) //無參無傳回值
{

}

int main()
{
  int i=f(1,2,3) //error

  f();    //ok

  return 0;
}      

(2)不存在void變量

  ①C語言沒有定義void究意是多大記憶體的别名,沒有void标尺,無法在記憶體中裁出大小

#include<stdio.h>
void main()
{
     void var;        //error,不可以是void型的變量
     void array[5];   //error,同上
     void* pv;        //ok,void*的指針是可以的。
}      

  ②小貼士:ANSI C:标準C語言的規範

                    擴充C: 在ANSI C的基礎上進行了擴充

#include<stdio.h>

int main()
{
  //在ANSI C編譯器中無法通,支援GNU标準的gcc下為void大小為1,是合法的
  printf("sizeof(void)=%d\n",sizeof(void)); 
}      

(3)void指針的意義

  ①C語言規定隻有相同類型的指針才可以互相指派

  ②void* 指針作為左值用于“接收”任意類型的指針

  ③void* 指針作為右值使用時需要進行強制類型轉換

int* pI = (int*)malloc(sizeof(int));
char* pC = (char*)malloc(sizeof(char));
void* p = NULL;
int* pni = NULL;
char* pnc = NULL;

p = pI; //ok,void*指針p可接收任何類型的指針
pni = p; //error,void*須強制類型轉換,即pni =(int*)p;
p = pC;  //ok
pnc = p; //error,應為pnc=(char*)p;      

【程式設計執行個體】通過void*實作MemSet函數

#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];//這裡可以是任何其他類型,如char a[5];double a[5]等。
    int i = 0;
    
    MemSet(a, sizeof(a), 0);
    
    for(i=0; i<5; i++)
    {
        printf("%d\n", a[i]);
    }
    
    return 0;
}      

3. 小結

(1)現代軟體工程中禁用goto語句

(2)void是一種抽象的資料類型

繼續閱讀