在qsort的手册页中,在排序字符串的示例中:
static int
cmpstringp(const void *p1, const void *p2)
{
/* The actual arguments to this function are "pointers to
pointers to char", but strcmp(3) arguments are "pointers
to char", hence the following cast plus dereference */
return strcmp(* (char * const *) p1, * (char * const *) p2);
}
为什么在char * const *
的参数中需要strcmp()
? char *
不够吗?
答案 0 :(得分:3)
strcmp
被声明为
int strcmp(
const char *string1,
const char *string2
);
这正确地表达了函数的接口契约 - 即strcmp
不会修改其输入数据 - 并允许编译器在函数内部进行优化(假设它不是CRT的一部分,并且可能已经在汇编程序中)。
答案 1 :(得分:2)
const void* p1
表示此函数未更改p1
点。如果你做了
char** p1_copy = (char**) p1;
这将是一个潜在破坏承诺的设置,因为你可以做
*p1_copy = "Something else";
所以从const void*
到char**
的演员阵容被称为“抛弃const”。合法,但是如果你使用强制转换来抛弃const并以其他方式一次更改类型,一些编译器会发出警告。
没有违反const void* p1
声明承诺的演员阵容是使用的:
char* const* p1_arg = (char* const*) p1;
现在*p1_arg
,p1
指向的东西,不能像我们说的那样改变。你可以改变它中的字符:
*p1_arg[0] = 'x';
函数声明从未说过任何关于它们的内容,并且你说你知道它们原来是非const char
的。所以它是允许的,即使该函数实际上没有做任何这样的事情。
然后你取消引用(作为一个rvalue)来获得char*
。这可以通过自动const char*
促销合法地作为strcmp
参数传递给const
。
答案 2 :(得分:1)
从技术上讲,如果你想摆脱这些争论,演员阵容将是char **
,而不是char *
。由于const
的参数也是cmpstringp
,因此const
会留在演员表中。
答案 3 :(得分:0)
传递给qsort的比较函数没有业务修改它正在比较的项目。
这就是为什么qsort的一般情况如下:
void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));