1. 程式人生 > >C語言進階剖析 08 goto 和 void 分析

C語言進階剖析 08 goto 和 void 分析

文章目錄


例項分析: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); STATUS: p[0] = n; printf("void func(%d) = %d.\n",n,p[0]); free(p); } int main() { printf("begin ...\n"); printf("void func( 1 ) :\n"); func(1); printf("void func( -1 ) :\n"); func(-1); printf(
"end ...\n"); return 0; } printf("void func( 1 ) :\n"); func(1); printf("void func( -1 ) :\n"); func(-1); printf("end ...\n"); return 0; }
begin ...
void func( 1 ) :
void func(1) = 1.
void func( -1 ) :
Segmentation fault

分析:
破壞了程式的結構化特性(順序執行,條件執行,迴圈執行);
增加閱讀與除錯難度。


void 的意義

  • void 修飾函式返回值和引數
        ○ 如果函式沒有返回值,那麼應該將其宣告為 void
        ○ 如果函式沒有引數,應該宣告引數為 void
        ○ void 修飾函式返回值和引數是為了表示 "無"
#include <stdio.h>

func()
{
}
        
int main()
{
    int i = func(1, 2, 3);
    
    printf("%d\n", i);

    return 0;
}
    輸出:(編譯器無警告,無報錯,輸出隨機值)
    -1074333820
    
    分析:
    沒有寫引數,意味著可以接收任意多引數
    沒有寫返回值,意味著返回值為 int
  • 不存在 void 變數 (可理解void是一個抽象型別)
        ○ C 語言沒有定義 void 究竟是多大記憶體的別名
        ○ 沒有 void 標尺,無法在記憶體中裁剪出 void 對應的變數
void code()
{
    void var;
    void array[5];
    void* pv;
}  
  • 小貼士
        ○ ANSI C : 標準 C語言的規範
        ○ 擴充套件 C : 在 ANSI C 的基礎上進行了擴充
        ○ C 語言的灰色地帶
void code()
{
    printf("%d\n", sizeof(void));
}
上面的程式碼在 ASNI C編譯器(BCC)中無法通過編譯,但是對於支援 GNU 標準的 gcc 編譯器而言是合法的。
BCC : Error
GCC : 1

  • void 指標的意義
        ○ C 語言規定只有相同型別的指標才可以互相賦值
        ○ void* 指標作為左值用於 接收 任意型別指標
        ○ void* 指標作為右值使用時需要進行強制型別轉換
        ○ 指標為相應機器的固定寬度,可以裁剪相應的記憶體大小,所以可以定義 void* 指標
void code()
{
    int* pI   = (int*)malloc(sizeof(int));
    char* pC  = (char*)malloc(sizeof(int));
    void* p   = NULL;
    int* pni  = NULL;
    char* pnc = NULL;
    
    p = pI;  // OK
    pni = p; // oops!
    
    p = pC;     // OK
    pnc = p; // oops!  
}

例項分析:通過 void* 實現 MemSet 函式

#include <stdio.h>

void MemSet(void * src,int lenth, unsigned char n)
{
	unsigned char * p= (unsigned char*)src;
	int i = 0;
	for (i=0;i<lenth;i++) 
	{
		p[i] = n;
	}
}

int main()
{
	int  a[5];
	int i = 0;
	MemSet(a,sizeof(a),0);
	printf("%d.\n",sizeof(a));
	for(i=0;i<5;i++)
	{
		printf("%d.\n",a[i]);
	}	
}
輸出:
20.
0.
0.
0.
0.
0.

小結

  • 現代軟體工程中禁用 goto 語句
  • void 是一種抽象的資料型別
  • void 資料型別不能用於定義變數
  • void 型別用於宣告函式無引數
  • void 型別用於宣告函式無返回值
  • 可以定義 void 型別的指標*
  • void* 型別的指標可以接收任意型別的指標

內容參考狄泰軟體學院系列課程,如有侵權,請聯絡作者刪除!感謝~