qsort要求比较函数为c风格函数指针,不可用lambda或成员函数;结构体含std::string时禁用qsort;其不稳定且无类型检查,易因sizeof误用导致未定义行为;c++项目应优先使用std::sort。

qsort 的比较函数必须是 C 风格函数指针,不能用 lambda 或成员函数
这是最常卡住的地方:qsort 是 C 标准库函数,只接受 int (*)(const void*, const void*) 类型的比较函数。C++ 中直接传 lambda(哪怕加 static)或类成员函数会编译失败,报错类似 cannot convert 'lambda' to 'int (*)(const void*, const void*)'。
正确做法是写一个独立的、非模板、非内联、非捕获的普通函数:
int cmp_int(const void* a, const void* b) {
int ia = *(int*)a;
int ib = *(int*)b;
return (ia > ib) - (ia <p>调用时注意类型强转和元素大小:</p><pre class="brush:php;toolbar:false;">int arr[] = {3, 1, 4, 1, 5};
size_t n = sizeof(arr) / sizeof(arr[0]);
qsort(arr, n, sizeof(int), cmp_int); // 第三个参数必须是 sizeof(int),不是 sizeof(*arr) 的宏展开陷阱排序 char* 数组时,比较函数要解两层指针
比如你有个字符串数组 char* names[] = {"bob", "alice", "zoe"},qsort 传给比较函数的是 char** 类型的两个地址(即指向指针的指针),不是 char*。
常见错误是直接用 strcmp(a, b),导致段错误或乱序。
正确解法:
const char** pa = (const char**)a;const char** pb = (const char**)b;- 再用
strcmp(*pa, *pb)
int cmp_str(const void* a, const void* b) {
const char** pa = (const char**)a;
const char** pb = (const char**)b;
return strcmp(*pa, *pb);
}
// 调用
char* names[] = {"bob", "alice", "zoe"};
qsort(names, 3, sizeof(char*), cmp_str); // 注意:sizeof(char*),不是 sizeof(char)
自定义结构体排序要确保内存布局和对齐安全
对结构体数组排序时,qsort 按字节拷贝,不调用构造/析构函数,所以结构体里不能有指针成员(除非你明确管理其生命周期)、不能有虚函数、不能有 non-trivial 成员(如 std::string)。
例如这个结构体可以安全排序:
struct Point {
int x;
int y;
};
比较函数示例(先按 x 升序,x 相等时按 y 降序):
int cmp_point(const void* a, const void* b) {
const Point* pa = (const Point*)a;
const Point* pb = (const Point*)b;
if (pa->x != pb->x) return pa->x - pb->x;
return pb->y - pa->y; // 注意这里是降序
}
qsort(pts, n, sizeof(Point), cmp_point);
如果结构体含 std::string,qsort 的位拷贝会破坏内部指针,程序大概率崩溃——这种场景必须改用 std::sort。
qsort 不稳定,且没有模板推导,类型错误只能靠人盯
qsort 不保证相等元素的相对顺序(不稳定排序),且所有类型信息都在运行时靠 sizeof 和指针强转维持。编译器无法检查 sizeof 是否匹配实际元素类型,比如把 sizeof(double) 写成 sizeof(float),会导致越界读写,行为未定义。
几个关键点要手动核对:
- 数组首地址传的是
&arr[0]还是arr?两者等价,但别传&arr(那是整个数组地址) -
nmemb参数是元素个数,不是字节数 - 比较函数返回值逻辑必须严格满足:负数表示小于,0 表示等于,正数表示大于;不能只返回 1 或 0
真要图省事又安全,C++ 项目里优先用 std::sort;只有对接 C 接口、或在受限环境(如嵌入式裸机)才硬上 qsort。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











