[英]Sort example from C++ Programming Language
我正在使用“ C ++編程語言”中的以下示例代碼:
typedef int (*CFT) (const void*, const void*);
void ssort(void* base, size_t n, size_t sz, CFT cmp) {
for (int gap = n / 2; 0 < gap; gap /= 2) {
for (int i = gap; i < n; i++) {
for (int j = i - gap; 0 <= j; j -= gap) {
char* b = static_cast<char*>(base);
char* pj = b + j * sz;
char* pig = b + (j + gap) * sz;
if (cmp(pig, pj) < 0) {
for (int k = 0; k < sz; k++) {
std::swap(pj[k], pig[k]);
}
} else {
break;
}
}
}
}
}
int cmp(const void* a, const void* b) {
return *(static_cast<const int*>(a)) - *(static_cast<const int*>(b));
}
誰能解釋這些對char *的強制轉換是關於什么的? 我們如何使用char *指向任何類型的值?
請記住,這是一個示例,通過說明處理泛型時C
編程中的弱點來演示如何在C ++中 不執行操作。
Quote: C ++編程語言 (第4版,第334頁)
這種代碼風格在C語言中很常見,但這並不是在C ++中表達此算法的最優雅的方式
然而:
char* b = static_cast<char*>(base);
char* pj = b + j * sz;
char* pig = b + (j + gap) * sz;
的原因 void
指針轉換為char
球是因為你不能對指針運算void*
。
指針算術以指針指向的對象大小為單位 。 因此,要執行指針算術運算,編譯器需要知道指針的類型 ,以便它知道如何對其值進行加減。
對於void*
這是不可能的,因為void
沒有大小。 通過接受void*
參數,原始類型已丟失。
為了解決這個問題,算法將void*
強制轉換為char*
。 該char*
工作在一個大小單位。 然后,該函數希望用戶將每個元素的實際大小作為另一個參數傳遞。
編譯器可以輕松地對所得的char*
進行算術運算。
因為ssort()
函數不知道元素的類型 ,所以調用者還需要傳遞自己的函數來進行元素之間的比較,從而對元素進行排序。 請注意, 傳入的函數將void*
參數轉換為正確的類型。
之所以ssort()
是因為調用ssort()
函數的人知道要排序的類型 ,而ssort()
函數則不需要。
這給函數調用者帶來了很多負擔,並且存在很多導致細微或不細微錯誤的錯誤空間。
像 C++
的瘟疫一樣,應避免此類編程 。
總結一下:
ssort()
函數將void*
強制轉換為char*
以便它可以執行指針算術來定位需要比較的元素。
調用者傳入自己的函數(cmp),該函數將void*
強制轉換為正確的類型以進行比較。
static_cast<T>
只是嘗試將類型轉換為T
看這里的例子-
float f = 12.3;
float* pf = &f;
// static cast<>
// OK, n = 12
int n = static_cast<int>(f);
// Error, types pointed to are unrelated
//int* pn = static_cast<int*>(pf);
// OK
void* pv = static_cast<void*>(pf);
// OK, but *pn2 is rubbish
int* pn2 = static_cast<int*>(pv);
// reinterpret_cast<>
// Error, the compiler know you should
// call static_cast<>
//int i = reinterpret_cast<int>(f);
// OK, but *pn is actually rubbish, same as *pn2
int* pi = reinterpret_cast<int*>(pf);
禮貌: 靜態演員實際在做什么
並且您不能使用char*
指向任何類型的值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.