C語言進階剖析 08 goto 和 void 分析
阿新 • • 發佈:2019-01-12
文章目錄
例項分析: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* 型別的指標可以接收任意型別的指標
內容參考狄泰軟體學院系列課程,如有侵權,請聯絡作者刪除!感謝~