C/C++中的void和void*
阿新 • • 發佈:2019-01-05
一、void
void關鍵字表示“空型別”的概念。但是,這裡的“空型別”不表示“任意型別”,而是表示不存在的意思,也就是說C/C++不允許你寫語句void a,不存在型別為void的東西.
void表示“不存在”的意思,可以從void的兩個應用中加以體現:
1、void作為函式的返回值型別時,表示函式返回值不存在,即函式沒有返回值。
例如:
void FunctionNoReturn_0(std::string strName)
{
std::cout << strName << std::endl;
return;
}
void FunctionNoReturn_1(std::string strName)
{
std::cout << strName << std::endl;
}
FunctionNoReturn_1函式體中雖然沒有顯式的Return;語句。但是,有隱式的Return;表示函式不存在返回值。
FunctionNoReturnType(void)
{
return 10;
}
在C語言中,凡是不加返回值型別限定的函式,就會被編譯器作為返回整型值處理,而不是沒有返回值。所以,FunctionNoReturnType函式返回10是正確的。
在C++中,每個函式必須限定返回值型別,不允許不加返回值限定。所以,C++編譯器會對FunctionNoReturnType報錯。
2、void作為函式的引數的限定時,表示函式形參不存在,即函式沒有形參。
例如:
void FunctionNoArgument_0(void)
{
return;
}
void FunctionNoArgument_1()
{
return;
}
注意:void FunctionNoArgument_1();這也表示沒有形參。
在C語言中,FunctionNoArgument_1(10);是合法的。編譯器不會報錯。
在C語言中,FunctionNoArgument_0(10);是不合法的。編譯器會報錯。
在C++語言中,FunctionNoArgument_1(10);和FunctionNoArgument_0(10);
都是不合法的。編譯器會報錯。
C語言中不報錯,也沒什麼關係的。因為,引數10對於函式的執行的結果沒有影響。但是,對於程式碼的維護可能會造成隱藏的危害,可能會給別人造成誤解。
說明:既然提供了void的這兩種用法,就去運用。即函式沒返回值就將其返回值型別寫為void,函式沒有形參就將其形參寫為void。不瞭解編譯器預設操作時,不要依賴。即使瞭解其預設操作,也別依賴,因為肯定有人不瞭解的,這樣別人就看不懂你的程式碼了。
二、void*
void*表示“空型別指標”,與void不同,void*表示“任意型別的指標”或表示“該指標與一地址值相關,但是不清楚在此地址上的物件的型別”。(為什麼不用void表示任意型別的資料呢?大家都知道,C/C++是靜態型別的語言,定義變數就會分配記憶體,然而,不同型別的變數所佔記憶體不同,如果定義一個任意型別的變數,如何為其分配記憶體呢?所以,C、C++中沒有任意型別的變數。但是,所有指標型別的變數,無論是int*、char*、string*、Student*等等,他們的記憶體空間都是相同的,所以可以定義“任意型別的指標”)。
C++/ANSI C:
void*指標只支援幾種有限的操作:與另一個指標進行比較;向函式傳遞void指標或從函式返回void*指標;給另一個void*指標賦值。不允許使用void*指標操作它所指向的物件,例如,不允許對void*指標進行解引用。不允許對void*指標進行算術操作。
GNU C:
GNU C指定void*指標的算術操作與char*一致。
void*表示“任意型別的指標”,主要運用於記憶體操作函式的形參型別和返回值型別(記憶體操作與記憶體中資料型別無關,即任意型別都可以)。
memcpy
原型:extern void *memcpy(void *dest, void *src, unsigned int count);
用法:#include
功能:由src所指記憶體區域複製count個位元組到dest所指記憶體區域。
說明:src和dest所指記憶體區域不能重疊,函式返回指向dest的指標。
注意:與strcpy相比,memcpy並不是遇到'\0'就結束,而是一定會拷貝完n個位元組。
memset
原型:extern void *memset(void *buffer, int c, int count);
用法:#include
功能:把buffer所指記憶體區域的前count個位元組設定成字元c。
說明:返回指向buffer的指標。
void關鍵字表示“空型別”的概念。但是,這裡的“空型別”不表示“任意型別”,而是表示不存在的意思,也就是說C/C++不允許你寫語句void a,不存在型別為void的東西.
void表示“不存在”的意思,可以從void的兩個應用中加以體現:
1、void作為函式的返回值型別時,表示函式返回值不存在,即函式沒有返回值。
例如:
void FunctionNoReturn_0(std::string strName)
{
std::cout << strName << std::endl;
return;
}
void FunctionNoReturn_1(std::string strName)
{
std::cout << strName << std::endl;
}
FunctionNoReturn_1函式體中雖然沒有顯式的Return;語句。但是,有隱式的Return;表示函式不存在返回值。
FunctionNoReturnType(void)
{
return 10;
}
在C語言中,凡是不加返回值型別限定的函式,就會被編譯器作為返回整型值處理,而不是沒有返回值。所以,FunctionNoReturnType函式返回10是正確的。
在C++中,每個函式必須限定返回值型別,不允許不加返回值限定。所以,C++編譯器會對FunctionNoReturnType報錯。
2、void作為函式的引數的限定時,表示函式形參不存在,即函式沒有形參。
例如:
void FunctionNoArgument_0(void)
{
return;
}
void FunctionNoArgument_1()
{
return;
}
注意:void FunctionNoArgument_1();這也表示沒有形參。
在C語言中,FunctionNoArgument_1(10);是合法的。編譯器不會報錯。
在C語言中,FunctionNoArgument_0(10);是不合法的。編譯器會報錯。
在C++語言中,FunctionNoArgument_1(10);和FunctionNoArgument_0(10);
都是不合法的。編譯器會報錯。
C語言中不報錯,也沒什麼關係的。因為,引數10對於函式的執行的結果沒有影響。但是,對於程式碼的維護可能會造成隱藏的危害,可能會給別人造成誤解。
說明:既然提供了void的這兩種用法,就去運用。即函式沒返回值就將其返回值型別寫為void,函式沒有形參就將其形參寫為void。不瞭解編譯器預設操作時,不要依賴。即使瞭解其預設操作,也別依賴,因為肯定有人不瞭解的,這樣別人就看不懂你的程式碼了。
二、void*
void*表示“空型別指標”,與void不同,void*表示“任意型別的指標”或表示“該指標與一地址值相關,但是不清楚在此地址上的物件的型別”。(為什麼不用void表示任意型別的資料呢?大家都知道,C/C++是靜態型別的語言,定義變數就會分配記憶體,然而,不同型別的變數所佔記憶體不同,如果定義一個任意型別的變數,如何為其分配記憶體呢?所以,C、C++中沒有任意型別的變數。但是,所有指標型別的變數,無論是int*、char*、string*、Student*等等,他們的記憶體空間都是相同的,所以可以定義“任意型別的指標”)。
C++/ANSI C:
void*指標只支援幾種有限的操作:與另一個指標進行比較;向函式傳遞void指標或從函式返回void*指標;給另一個void*指標賦值。不允許使用void*指標操作它所指向的物件,例如,不允許對void*指標進行解引用。不允許對void*指標進行算術操作。
GNU C:
GNU C指定void*指標的算術操作與char*一致。
void*表示“任意型別的指標”,主要運用於記憶體操作函式的形參型別和返回值型別(記憶體操作與記憶體中資料型別無關,即任意型別都可以)。
memcpy
原型:extern void *memcpy(void *dest, void *src, unsigned int count);
用法:#include
功能:由src所指記憶體區域複製count個位元組到dest所指記憶體區域。
說明:src和dest所指記憶體區域不能重疊,函式返回指向dest的指標。
注意:與strcpy相比,memcpy並不是遇到'\0'就結束,而是一定會拷貝完n個位元組。
memset
原型:extern void *memset(void *buffer, int c, int count);
用法:#include
功能:把buffer所指記憶體區域的前count個位元組設定成字元c。
說明:返回指向buffer的指標。