精华内容
下载资源
问答
  • 但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错。因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错。准确的来说,函数不能通过...

    一般的来说,函数是可以返回局部变量的。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错。但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错。因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错。准确的来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的)。

        下面以函数返回局部变量的指针举几个典型的例子来说明:

    1:可以返回指向字符串常量的局部指针

        #include <stdio.h>   
        char *returnStr()   
        {   
            char *p="hello world!";   
            return p;   
        }   
        int main()   
        {   
            char *str;   
            str=returnStr();   
            printf("%s\n", str);   
            return 0;   
        }  
    

     

     这个没有任何问题,因为"hello world!"是一个字符串常量,存放在只读数据段(全局变量数据区),把该字符串常量存放的只读数据段的首地址赋值给了指针,所以returnStr函数退出时,该该字符串常量所在内存不会被回收,故能够通过指针顺利无误的访问。

    2:可以返回局部变量,可以返回局部静态变量指针地址

        int func()  
        {  
              int a;  
              ....  
              return a;    //允许  
        }                     
          
        int * func()  
        {  
              int a;  
              ....  
              return &a;    //无意义,不应该这样做  
        }   
    

     

     局部变量也分局部自动变量和局部静态变量,由于a返回的是值,因此返回一个局部变量是可以的,无论自动还是静态,因为这时候返回的是这个局部变量的值,但不应该返回指向局部自动变量的指针(地址),因为函数调用结束后该局部自动变量被抛弃,这个指针指向一个不再存在的对象(野指针),是无意义的。但可以返回指向局部静态变量的指针,因为静态变量的生存期从定义起到程序结束。

    4:如果函数的返回值非要是一个局部变量的地址,那么该局部变量一定要申明为static类型。如下:

        #include <stdio.h>   
        char *returnStr()   
        {   
            static char p[]="hello world!";   
            return p;   
        }   
        int main()   
        {   
            char *str;   
            str=returnStr();   
            printf("%s\n", str);   
          
            return 0;   
        }   
    

     

     5: 数组是不能作为函数的返回值的,原因是编译器把数组名认为是局部变量(数组)的地址。返回一个数组一般用返回指向这个数组的指针代替,而且这个指针不能指向一个自动数组,因为函数结束后自动数组被抛弃,但可以返回一个指向静态局部数组的指针,因为静态存储期是从对象定义到程序结束的。如下:

        int* func( void )  
        {  
            static int a[10];  
            ........  
            return a;  
        }   
    

     写的很好! 但是第5点里,“返回一个数组一般用返回指向这个数组的指针代替”, 这里应该是返回指向数组首元素的的指针而不是数组的指针吧。

        char *getClassName(void)  
        {  
            static char className[50] = {0};  
            ......  
          
            return &className[0];  
        }  
    

     6:返回指向堆内存的指针(调用malloc函数得到的指针)是可以的

        char *GetMemory3(int num)  
        {  
          char *p = (char *)malloc(sizeof(char) * num);  
          return p;  
        }  
        void Test3(void)  
        {  
          char *str = NULL;  
          str = GetMemory3(100);  
          strcpy(str, "hello");  
          cout<< str << endl;  
          free(str);  
        }  
    

      程序在运行的时候用 malloc 申请任意多少的内存,程序员自己负责在何时用 free释放内存。动态内存的生存期由程序员自己决定,使用非常灵活。

     

    总结:

    • 1.函数可以返回局部变量(无论自动变量还是静态变量)的值,不能返回非静态局部变量的指针
    • 2.函数可以返回“static 局部变量”的指针,可以返回本函数调用malloc( )函数得到的局部指针

     

     

    参考资料:

    https://blog.csdn.net/u012252959/article/details/79346146

    https://bbs.csdn.net/topics/390797710

     

     

    转载于:https://www.cnblogs.com/shujuxiong/p/10925116.html

    展开全文
  • 在做列表中的栈这道题时,突然对函数能否返回局部变量的地址,比如自定义函数中的一个指针有一些疑惑,于是用下面的几个小程序做了验证 test1 #include <stdio.h> #include <string.h> char * fun(){ ...

    在做列表中的栈这道题时,突然对函数能否返回局部变量的地址,比如自定义函数中的一个指针有一些疑惑,于是用下面的几个小程序做了验证
    test1

    #include <stdio.h>
    #include <string.h>
    
    char * fun(){
        char *str = (char *)malloc(100);
        scanf("%s", str);
        if(!strcmp(str, "push")) strcpy(str, "PUSH");
        if(!strcmp(str, "push")) strcpy(str, "POP");
        return str;
    }
    int main(){
        char a[10];
        strcpy(a, fun());
        printf("%s", a);
        return 0;
    }
    

    结果
    在这里插入图片描述
    test2

    #include <stdio.h>
    #include <string.h>
    
    char * fun(){
        // char *str = (char *)malloc(100);
        char str[100];
        scanf("%s", str);
        if(!strcmp(str, "push")) strcpy(str, "PUSH");
        if(!strcmp(str, "push")) strcpy(str, "POP");
        return str;
    }
    int main(){
        char a[10];
        strcpy(a, fun());
        printf("%s", a);
        return 0;
    }
    

    结果
    在这里插入图片描述
    test2

    #include <stdio.h>
    #include <string.h>
    
    char * fun(){
        // char *str = (char *)malloc(100);
        // char str[100];
        char static str[100];
        scanf("%s", str);
        if(!strcmp(str, "push")) strcpy(str, "PUSH");
        if(!strcmp(str, "push")) strcpy(str, "POP");
        return str;
    }
    int main(){
        char a[10];
        strcpy(a, fun());
        printf("%s", a);
        return 0;
    }
    

    结果
    在这里插入图片描述

    从上面的结果可以看出,c中不支持函数返回局部变量的地址,其实也就是常说的,函数中不能返回局部变量,因为在c中这些局部变量都是存储在栈中的,随着他们的作用域的消失而消失,局部变量的指针也是局部变量。如果我们要返回一个局部变量的指针,有两种方法,一、把这个指针声明为static。二、自己为这个指针所指的内容申请空间,这样的话只要自己没有释放这个变量,这个变量在整个程序的运行过程中就会一直存在。

    展开全文
  • #include ...//有关指针函数不可以返回局部变量的地址的三种解决方法#if 0 char *mystring(void) { //方法一:用static把局部数组改成静态数组 static char str[20]; strcpy(str,"Welcome li zhonghui
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    //有关指针函数不可以返回局部变量的地址的三种解决方法
    
    #if 0
    char *mystring(void)
    {
        //方法一:用static把局部数组改成静态数组
        static char str[20];
        strcpy(str,"Welcome li zhonghui!");
        return str;
    }
    #endif
    
    #if 0
    char *mystring(void)
    {
        //方法二:str指向一个字符串常量,字符串常量和静态变量类似,都是程序结束时,才释放内存
        char *str = "Welcome li zhonghui!";
        return str;
    }
    #endif
    
    #if 0
    int main()
    {
        //调用函数
        printf("%s\n",mystring());
    
        return 0;
    }
    #endif
    
    #if 1
    //方法三 指针函数返回一个堆空间上的地址
    char *mystring(void)
    {
        char *str = NULL;
        str = (char *)malloc(20);
        //一定记得要写出错判断
        if(NULL == str)
        {
            printf("malloc error\n");
            exit(1);    
        }
        strcpy(str,"Welcome li zhonghui!");
    
        return str;
    }
    
    int main()
    {
        char *s;
        s = mystring();
        if(NULL != s)
        {
            printf("%s\n",s);
            free(s);
        }
    
        return 0;
    }
    
    #endif
    
    
    展开全文
  • 函数里的局部变量一般都是按序排放的,并且因为是分配在堆栈之中,它们的地址是向下“增长”,即向低地址方向增长。比如下面的程序: int flag=0x12345678; printf("%x\n",flag); char s[6]; printf(“address ...

        函数里的局部变量一般都是按序排放的,并且因为是分配在堆栈之中,它们的地址是向下“增长”,即向低地址方向增长。比如下面的程序:

       int flag=0x12345678;
       printf("%x\n",flag);
    

    char s[6];
    printf(“address of flag: %x\n”,&flag);
    printf(“address of array s: %x\n”,s);
    strcpy(s,“my aaaa”);

    printf("%s\n",s);
    printf("%x\n",flag);
    printf("%c\n",*(char *)(&flag));//输出变量flag的第一个字节的内容

    上面的程序申明了一个变量flag并初始化为十六进制的12345678,以及一个字符型数组s。程序的运行结果如下图:





    从图中可以看出,程序执行时把变量flag分配的地址是0x28ff1c,而字符数组s的地址为0x28ff16,可以看到地址的增长方向是向下的,同时,s相对于flag的偏移量正好是字符数组s的大小,即6。在执行函数strcpy之前,可以把它们在内存中的布局表示如下(以字节为单位):


    因为我的机器中,数据的字节序是小端模式(小端模式即是:数据的高位保存在内存的高地址,而地位保存在内存的低地址,大端模式倒过来的),所以对于变量flag,其高位为0x12保存在最高地址处,而其低位的0x78保存在其变量的起始处。这样的话,当执行函数strcpy(s,"my aaaa")时,它会将从0x28ff16的地址处向上的连续的8个字节分别赋值为字符串“my aaaa”的每个字符(第8个字节是函数strcpy加上的一个字符串终止符0x00)。那么此时的内存情况如下:


    可以看到,执行strcpy函数时,它会将变量flag的前两个字节也改写了!(图中红色的表示被改写的,即flag的第一个字节被重新赋值为了字符‘a’,第二个字节被赋值为终止符0x00)。为什么会这样?因为strcpy函数并不检查目的缓冲区的大小边界,而是将源字符串逐一的全部赋值给目的字符串地址起始的一块连续的内存空间,同时加上字符串终止符

    所以最后输出变量flag时,其值变为0x12340061,即其高两字节未变,而最低位变为0x61即97,即字符a的ascii码,第二低字节变为0x00,即字符串终止符。

    所以,使用strcpy时容易出错,不幸的是,这种bug是不易被发现的。所以需要格外的小心。为了避免出错,可以使用另一个具有相同功能的函数: strncpy,该函数可以指定要复制的字符串的长度。

    展开全文
  • 1.问题描述  在C语言的一个函数中定义了几个局部变量如A,B,C。... 把被改变的变量的地址和A的地址打印出来,发现两者的地址差小于变量类型的地址。 3.举例 fun() { int a = 1, b = 2, c = 3; changeV
  • C++中不应该返回局部变量的地址

    千次阅读 2017-11-24 19:20:15
    在Effective C++中明确指出:不应该返回局部变量的引用,原因在于:局部变量会在函数返回后被销毁,因此被返回的引用就成为了”无所指”的引用,程序会进入未知状态。如果比较理解函数局部变量的作用域和生命周期,...
  • 最近在写代码的时候遇到返回局部...在Effective C++中明确指出:不应该返回局部变量的引用,原因在于:局部变量会在函数返回后被销毁,因此被返回的引用就成为了”无所指”的引用,程序会进入未知状态。如果比较理解...
  • 全局变量与局部变量的地址

    千次阅读 2010-12-18 13:26:00
    全局变量以及全局的函数名在编译时就已经分配地址了,而且这个地址是固定的线性地址,不管程序运行多少次,运行多少个实例,它的地址始终是确定的,而且是唯一的线性地址(线性地址通过分页机制转化成物理地址) //...
  • 在类中声明一个指针变量,并创建一个内部函数改变该指针变量的值。 (1).h文件 void readSettings(); QSettings *DialSettings; (2).cpp文件 void MainWindow::readSettings() { QSettings BasicSettings...
  •  很多书上或者说面试宝典呐之类的,都说不要返回一个局部变量的地址以供外部使用。怎么说呢,这种说法应该是基于编码习惯软件工程角度来说的,这种做法确实很容易出问题,但不是一定会出问题。下面我们来看一个简单...
  • 返回局部变量的地址

    千次阅读 2013-08-09 11:31:38
    我们可能会经常写出这样代码:int add(int a , int b){  return a + b;}当然,这是合理写法,使函数返回值为 int ,所以,调用函数后会返回一个int型值。 今天,我想讨论问题当然不是这个,请看下面这段...
  • char *getstring(void) { char p[]="hello everyone"; return p; } int main(int argc, char* argv[]) { printf("%s\n",getstring()); return 0; } char *getstring(void)函数中p数组是
  • ASLR(Address space layout randomization)是一种针对 缓冲区溢出 安全保护技术,通过对 堆、 栈、共享库映射等线性区布局随机化,通过增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到...
  • 局部变量的地址与栈

    2011-08-25 19:20:37
    个人定义了这三个变量,目的是想了解三个变量的地址之间的关系,每个变量都分配 4个字节,一个地址编号代表一个字节。 运行输出结果却是:1245052 1245048 1245044 , 为什么输出地址编号是从大到小的呢? 我以为...
  • 良好编程习惯太重要了,不然想做一个合格程序员很难。
  • C语言函数不能返回局部变量的地址

    千次阅读 2015-12-21 12:44:28
    但在很多情况下,我们需要从函数中返回多个值,此时使用数组或指针能够很好地完成这样任务。这里是一个示例。这个程序使用一个整型数组作为参数,并将数组元素和与积返回给调用函数。下面是C代码,这是一种常见...
  • C语言--返回局部变量的地址

    千次阅读 2013-07-27 13:02:36
    我们可能会经常写出这样代码:int add(int a , int b){ return a + b;}当然,这是合理写法,使函数返回值为 int ,所以,调用函数后会返回一个int型值。今天,我想讨论问题当然不是这个,请看下面这段代码...
  • 如果函数返回的是一个指针,且这个指针是指向函数体内创建的一个临时变量的话,将触发一级警告。 解决办法、 1 在临时变量前面加static关键字,使其作用周期变成整个函数内 2 在函数体内用new来声明空间,并在函数...
  • 原本想用一个for循环来向链表里增加... "位同学学号和成绩" << endl; stu s ; s.next = NULL; cin >> s.xuehao >> s.score; students.add(&s); cout<<&s<<endl; }
  • 现象: 下面代码,每次执行时,发现i的地址都不一样,j的地址每次相同。 #include int j; int main(void) ...但为什么i的地址不一样呢?...i是函数调用栈的第一个变量,如果栈基址每次运行一样的话,j的地址
  • $b = "dasdf"; function abc(){ $a = "abc"; global $b; ...在函数内部输出b的时候,是abc,但是离开函数后,输出b,又恢复成dasdf的...按理说,引用了一个局部变量的地址,这个局部变量销毁后,b的值应该是空啊。
  • for(int i=0;i<10;i++) { int j = i+1; cout<<&j<<...每一次循环,j的地址值都是一个,不是每一次循环的时候都会重新自动分配吗?为啥每次都是同一个地址呢? 新手求教

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,298
精华内容 3,319
关键字:

局部变量的地址