来自 C++ 编程语言的排序示例
Sort example from C++ Programming Language
我将在 "C++ Programming Language" 中查看以下示例代码:
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* 指向任何类型的值?
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);
礼貌:what static cast actually doing
并且您不能 user char*
指向任何类型的值。
记住这是一个示例,通过说明 C
编程中的弱点来演示 不是 如何在 C++ 中做事在处理 generics.
时
引用: C++ 编程语言(第 4 版第 334 页)
This style of code is common in C, but it is not the most elegant way
of expressing this algorithm in C++
然而:
char* b = static_cast<char*>(base);
char* pj = b + j * sz;
char* pig = b + (j + gap) * sz;
原因 void
指针被转换为 char
指针是因为你不能在 void*
上进行指针运算。
指针算法以指针指向的对象的大小的单位工作。所以要进行指针运算,编译器需要知道指针的类型,这样它才能知道如何对其值进行加减。
这对于 void*
是不可能的,因为 void
没有大小。通过接受 void*
参数,原来的 type 已经丢失。
为了解决这个问题,算法将 void*
转换为 char*
。 char*
以 one 的大小单位工作。该函数然后期望用户将每个元素的实际大小作为另一个参数传递。
编译器对结果 char*
.
进行算术运算没有问题
因为 ssort()
函数不知道它正在排序的元素的 类型 调用者还需要 传入 自己的函数来做元素之间的比较。请注意 传入的 函数会将 void*
参数转换为正确的类型。
这是有效的,因为调用 ssort()
函数的人知道要排序的 type 而 ssort()
函数不需要。
这给函数调用者带来了很大的负担,并且有 很多 的错误余地,导致细微或不那么细微的错误。
在 C++
.
中,应像避免瘟疫 一样避免此类编程
总结一下:
ssort()
函数将 void*
转换为 char*
以便它可以进行指针运算来定位需要比较的元素。
调用者 传入他们自己的函数 (cmp),该函数将 void*
转换为 正确的类型 ,以便进行比较
我将在 "C++ Programming Language" 中查看以下示例代码:
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* 指向任何类型的值?
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);
礼貌:what static cast actually doing
并且您不能 user char*
指向任何类型的值。
记住这是一个示例,通过说明 C
编程中的弱点来演示 不是 如何在 C++ 中做事在处理 generics.
引用: C++ 编程语言(第 4 版第 334 页)
This style of code is common in C, but it is not the most elegant way of expressing this algorithm in C++
然而:
char* b = static_cast<char*>(base);
char* pj = b + j * sz;
char* pig = b + (j + gap) * sz;
原因 void
指针被转换为 char
指针是因为你不能在 void*
上进行指针运算。
指针算法以指针指向的对象的大小的单位工作。所以要进行指针运算,编译器需要知道指针的类型,这样它才能知道如何对其值进行加减。
这对于 void*
是不可能的,因为 void
没有大小。通过接受 void*
参数,原来的 type 已经丢失。
为了解决这个问题,算法将 void*
转换为 char*
。 char*
以 one 的大小单位工作。该函数然后期望用户将每个元素的实际大小作为另一个参数传递。
编译器对结果 char*
.
因为 ssort()
函数不知道它正在排序的元素的 类型 调用者还需要 传入 自己的函数来做元素之间的比较。请注意 传入的 函数会将 void*
参数转换为正确的类型。
这是有效的,因为调用 ssort()
函数的人知道要排序的 type 而 ssort()
函数不需要。
这给函数调用者带来了很大的负担,并且有 很多 的错误余地,导致细微或不那么细微的错误。
在 C++
.
总结一下:
ssort()
函数将 void*
转换为 char*
以便它可以进行指针运算来定位需要比较的元素。
调用者 传入他们自己的函数 (cmp),该函数将 void*
转换为 正确的类型 ,以便进行比较