【C语言学习趣事】_函数返回后的地址_游离地址空间

本文通过一系列实验探讨了C语言中函数返回局部变量地址的现象,揭示了这种做法为何看似可行但实则存在隐患,并解释了多次调用同一函数返回相同地址的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  前些日子,在QQ群里面,发现一些朋友在讨论函数返回后,为什么值可以传递和地址传递的情况;我也感到很好奇,

于是就跟了一下。

int*  sum(int x,int y)
{
    int a;
    a=x|y;
    
    return &a;
}

  很显然这段代码,存在一些问题;但是在VC2008中编译一切正常,运行状态也一切正常。

下面是我的测试代码:

#include <stdio.h>

int*  sum(int x,int y)
{
    int a;
    a=x+y;
    
    return &a;
}
int getsum(int x,int y)
{
    return x+y;
}
int main(void)
{
    int *x;
    int a;
    x=sum(10,2);

    printf("*x=%d; x=%u\n",*x,x);
    
    a=getsum(1,2);
    x=sum(10,2);
    printf("*x=%d; x=%u\n",*x,x);

    *x=100;
    printf("*x=%d; x=%u\n",*x,x);
    getchar();
    return 0;
}

运行结果如下所示:

  这个就是运行的结果?但是为什么呢?  而且两次调用sum函数返回的地址完全一样。

为了测试,我决定将代码再进行异常改动。

#include <stdio.h>

int*  sum(int x,int y)
{
    int a;
    a=x+y;
    
    return &a;
}
int getsum(int x,int y)
{
    int* p;
    p=sum(10,2);

    printf("*x=%d; x=%u\n",*p,p);
    return *p;  
}
int main(void)
{
    int *x;
    int a;

    x=sum(10,2);
    printf("*x=%d; x=%u\n",*x,x);
    
    a=getsum(1,2);

    x=sum(10,2);
    printf("*x=%d; x=%u\n",*x,x);

    *x=100;
    printf("*x=%d; x=%u\n",*x,x); 

       

    getchar();
    return 0;
}

  代码依然坚挺的活着,而且顺利的运行,如下所示,只是在getsum里面调用sum函数,得到的地址与main函数中得到的不一样。

  而且可以发现,无论怎么调用,在main函数中调用sum,返回的地址一直是一样的?  这是怎么回事呢?

如果是这样的话,那么是否可以用这种方法动态分配地址呢?  是否可以我们free 一下看看。很不幸的是,失败了?

  提示:可能是heap——栈——异常中断了程序。

  为什么会这样呢?

原因可能是:

  1、C程序在运行的过程中,其地址空间是固定的;虽然是可重定向的,但是在“他”自己的线性空间,其地址空间是固定的,

也就是所函数调用的压栈的空间,其栈基址是固定的。

  2、由于压栈顺序是一致的,而且每次压栈时变量的offset是一定的。从左往右压栈,或者从右往左压栈都一样会得到这个结果。

因此就出现了上面的情况。

  那么怎样说明这个过程的不正常呢? 虽然他看起来能编译、链接和运行,结果也很正常。

#include <stdio.h>

int *x;

int*  sum(int x,int y)
{
    int a;
    a=x+y;
    
    return &a;
}
void getsum()
{
    x=sum(10,2);    
    printf("*x=%d; x=%u\n",*x,x); //第二个输出
}
int main(void)
{
    int a;

    x=sum(10,2);
    printf("*x=%d; x=%u\n",*x,x);  //第一个输出
    
    getsum();
    printf("*x=%d; x=%u\n",*x,x);  //第三个输出

    *x=100;
    printf("*x=%d; x=%u\n",*x,x);   //第四个输出 
getchar(); return 0; }

  可以发现,第一个输出,第二输出的 *x的值一样;  而第二个、第三个、第四个则是x的只一样。这又是为什么呢?

 我们在改一下:

 #include <stdio.h

int *x;

int*  sum(int x,int y)
{
    int a;
    a=x+y;
    
    return &a;
}

void getsum() { x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第二个输出 } int main(void) { int a; x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第一个输出 getsum(); printf("*x=%d; x=%u\n",*x,x); //第三个输出 *x=100; printf("*x=%d; x=%u\n",*x,x); //第四个输出 x=sum(10,2); printf("*x=%d; x=%u\n",*x,x); //第五个输出 getchar(); return 0; }

又或者这样测试一下:

  

#include <stdio.h>

int *x;

int*  sum(int x,int y)
{
    int a;
    a=x+y;
    
    return &a;
}

int*  sum1(int x,int y)
{
    int a;
    a=x+y;
    
    return &a;
}
void getsum()
{
    x=sum(10,2);    
    printf("*x=%d; x=%u\n",*x,x); //第二个输出
}
int main(void)
{
    int a;

    x=sum(10,2);
    printf("*x=%d; x=%u\n",*x,x);  //第一个输出
    
    getsum();
    printf("*x=%d; x=%u\n",*x,x);  //第三个输出

    *x=100;
    printf("*x=%d; x=%u\n",*x,x);   //第四个输出 


    x=sum1(10,2);
    printf("*x=%d; x=%u\n",*x,x);  //第五个输出

    getchar();
    return 0;
}

我们再改一下:

#include <stdio.h>

int *x;

int*  sum(int x,int y)
{
    int a;
    a=x+y;
    
    return &a;
}

int*  sum1(int c,int d)
{
    int a;
    a=c+d;
    *x=60;
    return x;
}
void getsum()
{
    x=sum(10,2);    
    printf("*x=%d; x=%u\n",*x,x); //第二个输出
}
int main(void)
{
    int a;

    x=sum(10,2);
    printf("*x=%d; x=%u\n",*x,x);  //第一个输出
    
    getsum();
    printf("*x=%d; x=%u\n",*x,x);  //第三个输出

    *x=100;
    printf("*x=%d; x=%u\n",*x,x);   //第四个输出 


    x=sum1(10,2);
    printf("*x=%d; x=%u\n",*x,x);  //第五个输出

    getchar();
    return 0;
}

  输出结果如下所示:

  发现x的地址可以一直引用。

  如果你要做一些坏事的话,这里就是一个可以利用的地方。  可以通过这个全局的x变量,来修改传递给函数的参数值。

这个实验就不做了。

  有兴趣的可以试一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值