冒泡排序函数接收指针而非数组名,因为数组名传参时自动退化为指针,int arr[] 与 int* arr 在参数中完全等价;直接用指针更明确意图,且避免误用 sizeof(arr) 获取长度(实际得指针大小而非数组大小),故必须显式传入长度参数 n。

冒泡排序函数为什么要接收指针而非数组名
因为数组名传参本质是退化为指针,int arr[] 和 int* arr 在函数参数里完全等价。直接传指针更明确意图,也避免误以为能用 sizeof(arr) 获取长度——实际得到的是指针大小(通常 8 字节),不是数组总字节数。
所以必须额外传入长度参数,否则无法知道要比较多少对相邻元素。
- 错误写法:
void bubble_sort(int arr[]) { int n = sizeof(arr)/sizeof(int); }→n永远是 1(64 位下甚至可能是 0) - 正确做法:显式传长度,比如
void bubble_sort(int* arr, int n) - 若用
std::vector,可调用.size(),但题目要求指针,就老实用n
指针版冒泡排序的核心循环怎么写
外层控制轮数(最多 n-1 轮),内层逐对比较并交换。关键点是用指针算术代替下标:比如第 i 个元素是 *(arr + i),而不是 arr[i] —— 两者等价,但前者强调“指针操作”这一前提。
示例核心逻辑:
for (int i = 0; i *(arr + j + 1)) {
int temp = *(arr + j);
*(arr + j) = *(arr + j + 1);
*(arr + j + 1) = temp;
}
}
}
- 内层上界是
n - 1 - i:每轮后最大值“沉底”,无需再比末尾已排好部分 - 交换时务必用临时变量,不能直接
*(arr+j) ^= *(arr+j+1)等异或技巧——指针可能指向同一地址(虽此处不会,但习惯上不冒险) - 若想提前终止(已有序),可加
bool swapped标志,但纯指针实现中常省略
调用时怎么传指针、容易在哪出错
常见错误是把栈数组地址传错,或混淆指针类型。比如声明 int a[5] = {3,1,4,1,5};,应传 a 或 &a[0],二者都等价于 int*;绝不能传 &a(类型是 int(*)[5],编译可能过但行为未定义)。
- 正确调用:
bubble_sort(a, 5); - 错误调用:
bubble_sort(&a, 5);→ 类型不匹配,GCC/Clang 会警告incompatible pointer types - 动态分配内存时:用
int* p = new int[5];,排序后记得delete[] p;,否则内存泄漏 - 若函数声明为
const int* arr,则无法修改内容——冒泡必须可写,所以参数必须是int* arr
和标准库 sort 对比有什么实际影响
手写指针版冒泡时间复杂度是 O(n²),而 std::sort 是 O(n log n),且经过高度优化。在真实项目中,除非教学或嵌入式极端受限场景,否则不应使用指针版冒泡。
- 性能差距明显:1000 个整数,冒泡最坏需 ~50 万次比较,
std::sort约 1 万次 - 稳定性:冒泡是稳定排序(相等元素不交换位置),
std::sort不保证稳定;如需稳定,得用std::stable_sort - 指针操作本身无额外开销,但手动管理边界极易越界——比如内层循环写成
j 就会访问 <code>*(arr + n),导致未定义行为
真正要注意的不是“怎么写对”,而是“为什么非得用指针写”——如果只是为了理解地址运算和内存模型,那就专注验证 arr[i] 和 *(arr+i) 等价性;如果为了效率或工程交付,直接用 std::sort 并传迭代器更安全。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











