两数之和——基于C语言双指针实现

📅 2026/6/27 5:08:57
两数之和——基于C语言双指针实现
1. 程序代码int* twoSum(int* numbers, int numbersSize, int target, int* returnSize) { int left 0; int right numbersSize - 1; * returnSize 2; while(left right) { int sum numbers[left] numbers[right]; if(sum target) { int* result (int*)malloc(sizeof(int) * 2); result[0] left 1; result[1] right 1; return result; } else if(sum target) { right --; } else { left ; } } return NULL; }2. malloc函数在C语言中malloc函数是用于动态内存分配的标准库函数它允许程序在运行时分配指定大小的内存块。这个函数定义在stdlib.h头文件中其原型为void *malloc(size_t size)其中size参数指定了要分配的内存块的字节数。2.1 为什么要使用这个函数如果写成下面这样int result[2]; // 函数内的局部数组 result[0] left 1; result[1] right 1; return result; // 返回数组首地址编译时就会报警告warning: function returns address of local variable运行后大概率得到乱码、程序崩溃属于典型的悬垂指针野指针问题。原因很简单函数内定义的局部变量包括数组都分配在栈内存上。函数执行结束返回时对应的栈帧会被系统自动销毁回收这块内存会被标记为 “空闲”后续其他函数调用会直接覆盖这块空间。函数返回的只是一个内存地址但地址对应的内存已经失效了调用者再去读取result[0]读到的就是未知的垃圾值甚至触发内存访问错误。打个通俗的比方栈内存就像酒店的临时房间函数调用 开房间住进去函数结束 退房。我们退房之后还把房间号留给别人别人再进去里面的东西早就被清理、换成别人的东西了。而malloc分配的是堆内存相当于我们自己长期租的房子只要我们不主动free退房房子和里面的东西就一直有效把地址给别人别人也能正常访问。2.2 为什么必须用malloc有两个层面的原因1. 语言规则层面C 语言规定不能返回局部数组的地址但可以返回堆内存的地址。 堆内存的生命周期由程序员手动管理不会随函数结束而销毁。你用malloc申请的内存只要调用者不调用free数据就一直有效完全可以安全地传回给函数调用方使用。2. 题目接口约定题目注释里明确写了规则The returned array must be malloced, assume caller calls free().意思就是返回的数组必须用 malloc 分配调用方会负责释放。 LeetCode 的测试框架拿到函数返回的指针后会读取里面的两个下标最后调用free()释放这块内存。如果返回的是栈上的局部数组地址free一个非堆内存地址会直接导致程序崩溃。2.3 补充为什么返回 int 变量就可以你可能会疑惑为什么return left这种返回普通变量就没问题 因为返回普通变量是值传递—— 返回的是变量的副本函数里的变量销毁了不影响返回的这个副本。 而返回数组名本质返回的是指针地址返回的只是地址的副本地址指向的内存已经被销毁了所以会出问题。2.4 总结函数内部自己用定义局部数组完全没问题用完就扔。要把数组传出函数、给外部调用者用必须用malloc在堆上分配保证内存生命周期足够长。3. return NULL这是C 语言的语法强制要求和题目逻辑无关目的是让编译器正常通过编译。C 语言有一条硬性规则只要函数声明了非void的返回类型这里返回值是int*就必须保证函数的每一条执行路径最终都有返回值。我们的代码里return result只写在if (sum target)的分支里只有 “找到解” 的时候才会触发返回。如果循环走完了都没找到解函数就会走到末尾此时如果没有return NULL编译器会直接报错warning: control reaches end of non-void function [-Wreturn-type]意思是 “函数执行到末尾了却没有返回值”属于语法不完整。而题目虽然说明 “输入保证有唯一解”但编译器不会理解题目描述它只会静态检查代码的所有分支。所以return NULL是一个兜底的语法兼容写法—— 在逻辑正确的前提下这行代码永远不会被执行到。