C语言:指针--与函数 形参设计 指针返回值
值传递是将变量的值复制一份传递给函数或方法。在函数内部对参数的任何修改不会影响原始变量。函数 传参 -->值传递(形参 对实参 值拷贝(副本))*padd=a+b;* pmul=a*b;int main(){}地址传递是将变量的内存地址传递给函数或方法。函数内部通过地址直接操作原始变量,因此对参数的修改会影响原始变量。指针函数是指返回值为指针类型的函数。返回类型 *函数名(参数列表)。
总结一下指针与函数的形参设计,首先了解封装函数主函数与指针之间的值传递和地址传递
一、值传递
1.定义
值传递是将变量的值复制一份传递给函数或方法。在函数内部对参数的任何修改不会影响原始变量。
2.特点
原始变量的值不会被修改。
函数内部操作的是参数的副本。
3.参数传递指针与形参修改实参的原理
在C语言中,函数传参的传递本质上是值传递(传递副本)。若需要通过形参修改实参的值,必须传递实参的指针(地址),(地址传递将在第二点说),并在函数内通过解引用操作修改指针指向的内存内容 。
例:场景:Operate 函数 实现 求两数和 两数之积
#include <stdio.h>
int Operate(int a,int b)
{
return a+b,a*b;//逗号表达式
}
int main()
{
int* p=Operate(1,2);
return 0;
}
上述代码存在问题,首先是逗号表达式,使得主函数中运用Operate函数时,a+b的结果将会被丢弃,返回a*b的值。第二就是main函数中尝试将Operate的返回值赋值给int*类型的指针p,类型不匹配。
要解决上述问题,解决方案:
①:定义数组,定义一个全局变量int arr[2];来延长数组生存周期
②:延长数组生存周期--static
static修饰局部变量(延长局部变量的生存周期)
③:通过参数带值
④:使用malloc(之后文章总结详细用法)
总结
函数 传参 -->值传递(形参 对实参 值拷贝(副本))
bool Operate(int a,int b,int* padd,int* pmul)
{
*padd=a+b;
* pmul=a*b;
return ture;
}
int main()
{}
二、地址传递
1.定义
地址传递是将变量的内存地址传递给函数或方法。函数内部通过地址直接操作原始变量,因此对参数的修改会影响原始变量。
2.特点
原始变量的值可能被修改。
函数内部操作的是原始变量的地址。
三:地址传参和值传参的区别
地址传参:形参对实参的地址拷贝,形参修改实参,传地址,解引用
优势:节省内存空间,形参和实参指向同一份地址空间
值传参:形参对实参值拷贝(副本),拷贝完内存独立
四、函数返回
函数 返回值 返回地址称为指针函数
注意:不能返回局部变量的地址
指针函数的定义
指针函数是指返回值为指针类型的函数。这类函数的声明形式为:返回类型 *函数名(参数列表)。例如:
int *getPointer(int value) {
static int data = value;
return &data;
}
返回地址的注意事项
不能返回局部变量的地址
这是一个非常重要的限制,因为局部变量在函数执行结束后就会被销毁,其内存空间会被释放。如果返回这样的地址,会导致程序出现未定义行为。例如:
// 错误的示例
int *dangerousFunction() {
int localVar = 10;
return &localVar; // 错误:返回局部变量的地址
}
安全的返回方式
-
返回静态变量的地址:静态变量在程序整个运行期间都存在
int *safeFunction1() { static int staticVar; return &staticVar; } -
返回全局变量的地址:
int globalVar; int *safeFunction2() { return &globalVar; } -
返回动态分配的内存地址:
int *safeFunction3() { int *ptr = (int *)malloc(sizeof(int)); *ptr = 100; return ptr; } -
返回传入参数的地址:
int *safeFunction4(int *param) { *param = 50; return param; }
内存管理注意事项
当返回动态分配的内存时,调用者有责任在不再需要时释放这些内存,否则会导致内存泄漏:
int *ptr = safeFunction3();
// 使用ptr...
free(ptr); // 必须释放内存
五、空指针和野指针
空指针解引用
空指针是指指向内存地址为0的指针。在大多数操作系统中,地址0是受保护的,不允许用户程序访问。解引用空指针会导致程序崩溃,通常表现为段错误或访问冲突。
空指针解引用的典型场景:
int *ptr = NULL;
int value = *ptr; // 解引用空指针,导致崩溃
避免空指针解引用的方法是在解引用前检查指针是否为NULL:
if (ptr != NULL) {
value = *ptr;
} else {
// 处理空指针情况
}
野指针解引用
野指针是指指向已释放或无效内存地址的指针。解引用野指针的行为是未定义的,可能导致程序崩溃、数据损坏或难以预测的行为。
野指针的常见来源:
int *ptr = (int *)malloc(sizeof(int));
free(ptr); // 内存释放后,ptr成为野指针
*ptr = 10; // 解引用野指针,未定义行为
避免野指针的方法包括释放内存后将指针置为NULL,并在解引用前检查指针有效性:
free(ptr);
ptr = NULL; // 释放后立即置空
if (ptr != NULL) {
*ptr = 10;
}
指针解引用崩溃的解决方案
使用智能指针(如C++的std::unique_ptr或std::shared_ptr)可以自动管理内存,减少空指针和野指针问题:
std::unique_ptr<int> ptr(new int(42));
if (ptr) { // 自动检查有效性
int value = *ptr;
}
更多推荐


所有评论(0)