void *
是C語言中的一種類型,你們都知道在大多數編程語言中,void
類型都表明所謂的空類型,好比一個函數的返回一個空類型void
,這是很常見的用法。注意:返回值爲void
並非沒有返回值,而是表明返回空類型,這就是你仍然能夠在這些函數中使用return
語句的緣由。只有一些語言的構造函數和析構函數纔沒有返回值,在這些函數中,不可使用return
語句,他們是有顯著的不一樣的,Objective-C是一門獨特的語言,它的類的初始化方法是一個普通方法,返回值是instancetype
(當前類的指針類型)類型。
void *
可能就稍微不爲人知一些,void *
在C語言中能夠表示人任意類型的指針。畢竟對於內存單元的地址而言,所謂它存儲的數據類型,只是每次取出的字節數不一樣而已,這些內存單元的地址自己並無什麼不一樣。下面會更好的體現這句話的含義。void *
的大小和普通類型的指針同樣,老是一個字,具體的大小因機器的字長而異,例如對於32位機器是4個字節,對於64位機器是8個字節。我沒有考證過16位的8086機器上指針的大小,由於8086的地址是20位的,這個有興趣的話能夠回去試一試。我的認爲指針的大小仍然是16位,由於20位是物理地址,而物理地址是由段地址和偏移地址計算出的,在彙編以後C語言的指針可能只是變成相對於段地址的偏移地址,畢竟對於8086而言數據通常老是在DS段中,而代碼通常老是在CS段中。(斜體字表明還沒有考證的說法)java
void *
類型,而void *
類型通常只能強制轉換爲其餘普通類型的指針,不然會出現警告或錯誤。void *
指向數組的狀況,這裏直接上代碼解釋了。void Swap(void *array, int x, int y, int mallocsize) { void *temp = malloc(mallocsize); memcpy(temp, array+mallocsize*x, mallocsize); memcpy(array+mallocsize*x, array+mallocsize*y, mallocsize); memcpy(array+mallocsize*y, temp, mallocsize); free(temp); }
temp
,可是這個函數是泛型的,對於memcpy
的使用稍後會介紹。須要注意的是,array
指向一個數組的話,不能直接用&array[x]
或者array+x
得到指向第x個元素的地址,由於void *
類型默認的指針偏移量是1,和char *
是相同的,這對於絕大多數類型來講都會出現錯誤。因此在使用的時候必須知道該泛型類型原來所佔的長度,咱們須要一個名爲mallocsize
的int
類型形參來告訴咱們這個值,在計算指針偏移的時候乘以它。這就至關於C++編程中的模版類型定義或者Java中的泛型參數了。void *
類型的指針,任什麼時候候都不能夠對其進行解引用運算(或者在課堂上老師習慣叫作「取內容」?),緣由是顯然的:void
類型的變量並不合法。因此若是想進行解引用運算,必須先將其轉換爲普通類型的指針。用於數組的時候還須要注意解引用運算符的優先級是高於加法的,因此要加括號,好比這樣:int a = *(array + mallocsize * x);
sizeof
運算符相信學過C語言的朋友都不會陌生,可是sizeof是一個運算符估計就沒多少人知道了,返回的類型是size_t
類型。sizeof
運算符返回某個類型所佔用的空間大小。這裏只說一點就是,若是對一個指針類型或者數組名(實際上數組名就是指針常量嘛)求sizeof
的話,返回結果老是一個字(見上面所述)。而對一個結構體類型求sizeof
,並非簡單的將結構體中各個類型的sizeof
求和獲得,而是要涉及到內存對齊問題,這裏很少作介紹了,詳細瞭解能夠訪問:如何理解 struct 的內存對齊? - 知乎。void * memcpy(void *, const void *, size_t);
string.h
,你們也看出來了,這個函數自己就是以void *
類型做爲參數和返回值,其實也很好理解,就是一個賦值的過程,進行內存拷貝。把第二形參指向的內存拷貝到第一形參,拷貝的字節數由第三形參指定。固然了第三個參數通常經過sizeof
運算符求出,這裏就不舉例子了。返回值我沒有研究過,也沒用過,若是有知道的朋友能夠評論區交流。void *
類型看成泛型指針,而後再輔以相似於mallocsize
的參數指定所佔內存大小,所佔內存大小經過sizeof
運算符求得,若是須要進行賦值的話,利用memcpy
函數完成,下面就直接給一個例子出來,是泛型的快速排序算法,說明這些問題:#ifndef Compare_h #define Compare_h #include <stdio.h> #include "JCB.h" int IsGreater(void *x, void *y); int IsGreaterOrEqual(void *x, void *y); int IsSmaller(void *x, void *y); int IsSmallerOrEqual(void *x, void *y); #endif /* Compare_h */
// // Compare.c // Job-Dispatcher // // Created by 路偉饒 on 2017/11/16. // Copyright © 2017年 路偉饒. All rights reserved. // #include "Compare.h" int IsGreater(void *x, void *y) { return *(int *)x > *(int *)y; } int IsGreaterOrEqual(void *x, void *y) { return *(int *)x >= *(int *)y; } int IsSmaller(void *x, void *y) { return *(int *)x < *(int *)y; } int IsSmallerOrEqual(void *x, void *y) { return *(int *)x <= *(int *)y; }
// // QuickSort.h // Job-Dispatcher // // Created by 路偉饒 on 2017/11/16. // Copyright © 2017年 路偉饒. All rights reserved. // #ifndef QuickSort_h #define QuickSort_h #include <stdio.h> #include <stdlib.h> #include <string.h> #include "Compare.h" void QuickSort(void *array, int left, int right, int mallocsize); #endif /* QuickSort_h */
// // QuickSort.c // Job-Dispatcher // // Created by 路偉饒 on 2017/11/16. // Copyright © 2017年 路偉饒. All rights reserved. // #include "QuickSort.h" void Swap(void *array, int x, int y, int mallocsize) { void *temp = malloc(mallocsize); memcpy(temp, array+mallocsize*x, mallocsize); memcpy(array+mallocsize*x, array+mallocsize*y, mallocsize); memcpy(array+mallocsize*y, temp, mallocsize); free(temp); } int QuickSortSelectCenter(int l, int r) { return (l+r)/2; } int QuickSortPartition(void *array, int l, int r, int mallocsize) { int left = l; int right = r; void *temp = malloc(mallocsize); memcpy(temp, array+mallocsize*right, mallocsize); while (left < right) { while ( IsSmallerOrEqual(array+mallocsize*left, temp) && left < right) { left ++; } if (left < right) { memcpy(array+mallocsize*right, array+mallocsize*left, mallocsize); right--; } while ( IsGreaterOrEqual(array+mallocsize*right, temp) && left < right) { right--; } if (left < right) { memcpy(array+mallocsize*left, array+mallocsize*right, mallocsize); left ++; } } memcpy(array+mallocsize*left, temp, mallocsize); return left; } void QuickSort(void *array, int left, int right, int mallocsize) { if (left>=right) { return; } int center = QuickSortSelectCenter(left, right); Swap(array, center, right, mallocsize); center = QuickSortPartition(array, left, right, mallocsize); QuickSort(array, left, center-1, mallocsize); QuickSort(array, center+1, right, mallocsize); }
Compare.h
的用處的問題,下面會揭曉答案。int
、float
、double
是能夠進行比較的,char
使用ASCII編碼方案的比較咱們也理解,String
類型甚至也是能夠比較的。可是若是在其餘語言中,對象之間如何進行比較呢?這就是個問題了。在C++中咱們能夠進行運算符重載,這樣就仍舊可使用比較運算符,藉助運算符重載函數來完成。不過對於Java、Objective-C這種語言該怎麼辦?並且若是傳入的泛型參數沒有實現對應的運算符重載函數怎麼辦?這時候就要引入一個協議的概念,簡單來講就是,若是某個類型想要做爲排序泛型函數的泛型參數,那你必須實現可比較的協議。這個協議在Swift語言中就稱爲Comparable
,這樣的話在編譯的時候,編譯器才知道這個泛型參數是能夠進行比較的,這樣才能完成咱們的操做,不然的話就會出現錯誤。這就是泛型中的協議問題。void *
做爲泛型類型,本質上是泛型指針。sizeof
求得並傳入泛型函數。void *
的默認偏移是1,對於絕大多數類型來講都是錯誤的,須要自行編程轉換。memcpy
函數進行泛型變量的拷貝和賦值。