【问题标题】:Returning an Array on the fly ( C )即时返回一个数组( C )
【发布时间】:2012-07-05 01:58:17
【问题描述】:

我有一个函数,我想返回一个 int 数组,但我不想为此创建一个变量,就像这样

 int* foo()
 {
       static int bar[]={1,2,3}; // edit thanks to comments
       return bar;
 }

为了解决这个问题,我尝试了这个:

       return (Uint8Type*)   gAppCanContext.BluetoothMacAddr[0] + MacAddr[1] + '-'\
               + gAppCanContext.BluetoothMacAddr[2] + MacAddr[3] + '-' ;

但它不起作用。我也试过这个:

return (Uint8Type*[]){ MacAddr[0] , MacAddr[1] + '-' MacAddr[3] ... };

它编译时会发出警告,如果我执行程序,它会冻结。 我也尝试过使用星号和 & 符号,但无法正常工作。

有可能吗?如果有,怎么做?

补充:我不能使用 malloc - 是一个没有动态分配的嵌入式系统。

【问题讨论】:

  • 您的foo 函数实际上不起作用。除了将字符串存储在 int[] 中之外,使用它的返回值会导致未定义的行为。使用malloc
  • 你不能在 C 中以这种方式连接字符串。字符串只是指针——添加会更改指针偏移量而不是附加字符。
  • 那么,不管你的代码的问题,为什么讨厌变量?

标签: c arrays return


【解决方案1】:

它编译时会发出警告,如果我执行程序,它会冻结。

该警告告诉您正在返回一个即将死亡的对象的地址,因此在函数调用结束后访问它是非法的。

有可能吗?如果有,怎么做?

  • 你可以malloc一些内存并返回一个指向它的指针
  • 您可以使用 static 对象,如 Electro 所述。

【讨论】:

    【解决方案2】:

    如果 foo 中的数据不是动态的,你可以试试这个:

    const char *foo(void)
    {
        static const char *bar[] = {"aa", "bb", "cc"};
        return bar;
    }
    

    在“静态”的帮助下,数据在超出范围时不会消失。

    【讨论】:

    • 可能也想给bar添加一个类型。
    • 另外,可重新输入是个大问题
    • 请注意,这是非常糟糕的做法。它不是面向对象的设计,也不是线程安全的。
    • 是的,我错过了 bar 的类型...请使用 static const char *bar[]
    • @Rango,您可以(并且应该)编辑您的答案,而不是将其发布在 cmets 中(答案下方有一个编辑链接)。此外,您可以编辑任何人的答案和问题。我们本可以编辑你的,但我们把它留给你,这样你就习惯了,干杯。
    【解决方案3】:
    int* foo()
    {
       int bar[]={"aa","bb","cc"};
       return bar;
    }
    

    没有办法。 C 并没有真正的“数组”;当您返回 bar 时,它实际上只会返回指向 bar 的第一个元素的指针,当您返回调用者时,该指针将消失。

    除此之外,您可能需要决定在数组中是要“字符串”还是整数 :-)

    你可以将数组粘贴到结构中

    struct Weird
    {
        int bar[3];
    }
    

    然后返回:

    struct Weird foo(void)
    {
        struct Weird bar;
        bar.bar[0]=1;
        bar.bar[1]=5;
        bar.bar[2]=10;
        return bar;
    }
    

    不过,我不确定这就是你想要的。我猜你真的很想熟悉 C :-)

    如果你这样做,你也可以让你的第一个例子工作

    int* foo()
    {
       static int bar[]={1,2,3};
       return bar;
    }
    

    但是,当然,这只会创建数组的一个实例——所以如果你修改它,所有这些返回值都会被改变。

    【讨论】:

    • 我想变得更好,我可以走简单的路或找到捷径。
    【解决方案4】:

    除非标准发生变化,否则 C 会返回可以在寄存器中返回的值。因此,在您的情况下,您的函数将返回一个指向字符串的指针。

    如何创建该字符串取决于您考虑最佳实践。

    你可以在函数中声明一个静态数组并返回一个指向它的指针:

    char * cp1()
    {
        static char szForeverBuf[100] = {0};
    
        return (char * ) &szForeverBuf;
    }
    

    如果 cp1 在启动时被调用一次,但多次调用可能并且可能会导致错误,这可能是一种处理事情的好方法,因为该函数仅返回在编译时创建的缓冲区的地址。

    换句话说,函数 cp1 每次调用 cp1 时都会返回一个字符指针,其值永远不会改变。因此,这就是该函数在启动时可能有用的原因。

    你也可以像这样创建动态内存:

    #include <stdio.h>
    #include <stdlib.h>
    
    char * cp2(int nSizeP)
    {
        char *pszForeverBuf = NULL;
        int nSize = 0;
    
        if (0 >= nSizeP)
        {
            nSize = 100;
        }
        else
        {
            nSize = nSizeP + 1;
        }
    
        pszForeverBuf = (char *) malloc((nSize + 1) * sizeof(char));
    
        return pszForeverBuf; 
    }
    

    您需要将 pszForeverBuf 的值存储在某处,因此当您不再想使用内存时,可以使用 pszForeverBuf -- free(pszForeverBuf) 释放它。

    最后——更高级——您可以创建一个巨大的静态存储块,然后使用执行内存管理的函数对其进行操作。但是,这是在高级情况下使用的,当您不想多次调用 malloc 时。

    【讨论】:

      【解决方案5】:

      首先,C 中的函数不能返回数组值,只能返回指针。然后你不能返回一个动态的“堆栈”分配对象,正如其他人已经指出的那样,因为当你从函数返回时,这样的对象不再存在。

      我发现处理此类事情的最简单方法是将数组(指向)作为参数传递给函数:

      int* foo(int bar[3]) {
        // fill the array here
      
        return bar;
      }
      

      这让您可以使用两种不同的分配策略调用您的函数

      int* aMalloc = foo(malloc(sizeof(int[3])));
      int* aLocal = foo((int[3]){ 0 });
      

      然后您甚至可以将这两种形式封装到宏中,以简化您的编码:

      #define fooMalloc() foo(malloc(sizeof(int[3])))
      #define fooLocal() foo((int[3]){ 0 })
      

      所以上面的代码会这样读

      int* aMalloc = fooMalloc();
      int* aLocal = fooLocal();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-11-20
        • 2012-04-01
        • 2018-04-08
        • 2011-01-25
        相关资源
        最近更新 更多