#include void c_BinaryInsertionSort(void* base, c_size_t num, c_size_t size, c_SortCompare_t cmp, void* args) { // 边界与防御性校验:元素少于 2 个或参数非法时无需排序 if (!base || num < 2 || size == 0 || !cmp) { return; } char* array_base = (char*)base; // 栈上开辟局部单元素缓冲区,用于暂存待插入的临时变量 v,规避 malloc 堆碎片 char v_buf[size]; // 外层循环:从第二个元素开始(无符号安全递增) for (c_size_t i = 1; i < num; i++) { const char* item_i = array_base + (i * size); // 暂存当前需要插入的元素:v = a[i] memcpy(v_buf, item_i, size); // ----------------------------------------------------------------- // 核心:在已排好序的左侧区间 [0, i-1] 内执行二分查找,锁定 v 应该插入的绝对位置 // ----------------------------------------------------------------- c_size_t low = 0; c_size_t high = i; // 右边界设为 i(开区间),这样 high 永远不会递减到负数 while (low < high) { // 注意:开区间控制条件为 low < high,而不是 <= c_size_t mid = low + ((high - low) >> 1); char* mid_elem = array_base + (mid * size); // 执行您带 args 的自定义比对器 int cmp_res = cmp(v_buf, mid_elem, args); if (cmp_res < 0) { high = mid; // 目标值比 mid 小,直接收缩右开边界为 mid。彻底规避了 mid - 1 导致的下溢! } else { low = mid + 1; // 目标值 >= mid,向右半区逼近(保持稳定性) } } // 此时 low == high,这个值就是新元素应该插入的精准无符号下标位置 c_size_t insert_pos = low; // ----------------------------------------------------------------- // 数据搬运:将区间 [insert_pos, i-1] 内的元素统一单向往后平移一位 // 为确保绝对不发生 c_size_t 下溢,我们采用从后往前的减法前置拦截法 // ----------------------------------------------------------------- for (c_size_t j = i; j > insert_pos; j--) { char* current = array_base + (j * size); char* previous = array_base + ((j - 1) * size); memcpy(current, previous, size); // a[j] = a[j-1] } // 将暂存的元素 v 写入最终空出来的安全插槽:a[insert_pos] = v char* item_target = array_base + (insert_pos * size); memcpy(item_target, v_buf, size); } }