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聲明) |
| |
(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是一種抽象的資料類型