8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何使用指针从不同的函数访问局部变量?

Sheesh Abby 2月前

125 0

我可以访问不同函数中的局部变量吗?如果可以,该怎么做?void replaceNumberAndPrint(int array[3]) { printf(\'%i\n\', array[1]); printf(\'%i\n\', array[1]);}int * getAr...

我可以访问其他函数中的局部变量吗?如果可以,该怎么做?

void replaceNumberAndPrint(int array[3]) {
    printf("%i\n", array[1]);
    printf("%i\n", array[1]);
}

int * getArray() {
    int myArray[3] = {4, 65, 23};
    return myArray;
}

int main() {
    replaceNumberAndPrint(getArray());
}

上面这段代码的输出:

65
4202656

我做错了什么?“4202656”是什么意思?

我是否必须在函数中复制整个数组 replaceNumberAndPrint() 才能比第一次更频繁地访问它?

帖子版权声明 1、本帖标题:如何使用指针从不同的函数访问局部变量?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Sheesh Abby在本站《c》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 在这里很难知道最适合您意图的建议。但您可能想阅读共享指针(shared_ptr 和朋友)。它们通过执行引用计数提供了垃圾收集语言的一些良好属性。但不同,所以要小心。

  • @AnttiHaapala 问题中没有什么与 C++ 相关的独有内容,但不幸的是,有 C++ 答案,因此标签必须保留。

  • 如果在嵌入式系统上使用,那么动态分配内存是危险的,因此有 3 种可能性,使变量全局化,使其成为静态的,或者从调用例程中传递指向变量的指针。

  • myArray 是局部变量,因此指针仅在其作用域(在本例中为包含函数 getArray )结束之前有效。如果稍后访问它,则会出现未定义的行为。

    实际上发生的情况是,对的调用 printf 覆盖了所使用的堆栈部分 myArray ,然后它包含一些其他数据。

    要修复代码,您需要在存在时间足够长的作用域中声明数组( main 示例中的函数),或者在堆上分配它。如果在堆上分配它,则需要手动释放它,或者在 C++ 中使用 RAII 释放它。

    我错过的一个替代方案(如果数组不是太大,则可能是这里最好的替代方案)是将数组包装到结构中,从而使其成为值类型。然后返回它会创建一个在函数返回后仍然存在的副本。 tp1 tp1答案

  • 使其成为静态具有完全不同的语义,特别是在多线程应用程序中,除非数组的内容是常量。

  • 我想说,推荐使用 static 作为此问题的解决方案是有害的,而且永远不会有帮助。对于新手来说,它变成了一种公式化的创可贴,无法真正理解问题并编写正确的代码,而当其他人继承新手的代码时,他们会对到处都是无意义的静态变量感到震惊。

  • 一旦超出范围,就无法访​​问局部变量。这就是局部变量的含义。

    当您在函数中访问数组时, replaceNumberAndPrint 结果是未定义的。它第一次似乎有效,这只是一个幸运的巧合。您指向的内存位置可能在堆栈上未分配,并且对于第一次调用仍然正确设置,但随后的调用 printf 通过在操作期间将值推送到堆栈来覆盖它,这就是第二次调用 printf 显示不同内容的原因。

    您需要将数组数据存储在堆上并传递一个指针,或者存储在保持在范围内的变量中(例如全局变量或主函数内范围内的变量)。

  • 尝试类似的东西。你这样做的方式会“杀死”它, myArray 因为它是本地定义的。

    #include <stdio.h>
    #include <stdlib.h>
    
    void replaceNumberAndPrint(int * array) {
     printf("%i\n", array[0]);
     printf("%i\n", array[1]);
     printf("%i\n" , array[2]);
     free(array);
    }
    
    int * getArray() {
     int * myArray = malloc(sizeof(int) * 3);
     myArray[0] = 4;
     myArray[1] = 64;
     myArray[2] = 23;
     //{4, 65, 23};
     return myArray;
    }
    
    int main() {
     replaceNumberAndPrint(getArray());
    }
    

    更多信息: http://www.cplusplus.com/reference/clibrary/cstdlib/malloc/

    编辑: 正如评论正确指出的那样:更好的方法是:

    #include <stdio.h>
    #include <stdlib.h>
    
    void replaceNumberAndPrint(int * array) {
        if(!array)
            return;
    
        printf("%i\n", array[0]);
        printf("%i\n", array[1]);
        printf("%i\n" , array[2]);
    }
    
    int * createArray() {
        int * myArray = malloc(sizeof(int) * 3);
    
        if(!myArray)
            return 0;
    
        myArray[0] = 4;
        myArray[1] = 64;
        myArray[2] = 23;
        return myArray;
    }
    
    int main() {
        int * array = createArray();
        if(array)
        {
            replaceNumberAndPrint(array);
            free(array);
        }
        return 0;
    }
    
  • 如果您在代码中使用此功能,请务必对此“功能”进行非常好的注释。除非正确记录,否则由一个函数分配内存并由另一个函数释放内存是非常危险的,即使这样也容易发生内存泄漏!最好在主函数中分配数组并在不再需要时释放它。

  • @Shaihi,确实如此,而且这段代码非常幼稚,因为它没有检查 malloc() 是否分配成功。但我认为 OP 会理解这一点。

  • 虽然这可行,但效果很差。您应该更改函数名称(getArray => createArray)以更好地描述其行为。而且让 replaceNumberAndPrint 删除源数组对我来说似乎不是一个好主意。我宁愿将删除和打印分成两个不同的函数。

  • @Muggen:您不喜欢 array[i] 而不是 *(array+i) 吗?

  • 一旦离开 getArray,myArray 就会超出范围。您需要在堆上为其分配空间。

  • 您的代码调用了未定义行为,因为 myArray 一旦返回就超出范围 getArray() 使用 (取消引用)悬垂指针的 尝试

  • 局部变量在返回时超出范围,因此不能返回指向局部变量的指针。

    malloc 动态分配它(在堆上) new 。例如:

    int *create_array(void) {
        int *array = malloc(3 * sizeof(int));
        assert(array != NULL);
        array[0] = 4;
        array[1] = 65;
        array[2] = 23;
        return array;
     }
     void destroy_array(int *array) {
         free(array);
     }
     int main(int argc, char **argv) {
         int *array = create_array();
         for (size_t i = 0; i < 3; ++i)
             printf("%d\n", array[i]);
         destroy_array(array);
         return 0;
     }
    

    或者,你可以将数组声明为静态,但要记住语义是不同的。例如:

    int *get_array(void) {
        static int array[] = { 4, 65, 23 };
        return array;
     }
     int main(int argc, char **argv) {
         int *array = get_array();
         for (size_t i = 0; i < 3; ++i)
             printf("%d\n", array[i]);
         return 0;
     }
    

    如果你不知道是什么 static 意思,请阅读 this question & answer .

  • 正确的做法如下:

    struct Arr {
       int array[3];
    };
    Arr get_array() {
       Arr a;
       a.array[0] = 4;
       a.array[1] = 65;
       a.array[2] = 23;
       return a;
    }
    int main(int argc, char **argv) {
       Arr a = get_array();
       for(size_t i=0; i<3; i++)
           printf("%d\n", a.array[i]);
       return 0;
    }
    

    要理解为什么需要这样做,您需要知道 sizeof(array) 的工作原理。C(以及 c++)会尽力避免复制数组,而您需要结构来超越这一点。为什么需要复制是因为范围——get_array() 函数的范围消失了,并且该范围中仍然需要的每个值都需要复制到调用范围。

  • 我知道这已经是很久以前的事了,但是您是否不需要 typedef 或分配像 struct Arr a 这样的结构?

  • @sherrellbc 在 C 中,是的。在 C++ 中,struct Foo { ... }; 自动定义类型 struct Foo 和 Foo,不需要 typedef。

  • C++解决方案:

    \'我可以访问不同函数中的局部变量吗?如果可以,该怎么做?\'

    答案是不会,函数结束后就不会了。局部变量在函数结束时会被销毁。

    处理返回数组的方法是在 C++ std ::array (固定大小)或 (动态大小)这样 std::vector 容器

    例如:

    void replaceNumberAndPrint(const std::array<int, 3>& array) {
        printf("%i\n", array[0]);
        printf("%i\n", array[1]);
        printf("%i\n", array[2]);
    }
    
    std::array<int, 3> getArray() {
        std::array<int, 3> myArray = {4, 65, 23};
        return myArray;
    }
    

    在第二个函数中,返回的值已被编译器优化,因此您不必付出实际复制数组的代价。

返回
作者最近主题: