【问题标题】:How to return a C-style array of integers in Objective-C?如何在 Objective-C 中返回 C 风格的整数数组?
【发布时间】:2013-06-13 02:33:07
【问题描述】:

如何从 Objective-C 方法返回一个 C 风格的整数数组?这是我的代码到目前为止的样子:

函数调用:

maze = [amaze getMaze];

功能:

-(int*) getMaze{
    return maze;
}

我今天刚开始用 Objective-C 编写,所以这对我来说是全新的。

【问题讨论】:

  • 你给的代码有什么问题?
  • 它没有返回数组。
  • 什么是maze,您在哪里设置和访问它?
  • 你分配和初始化数组了吗?
  • 这是您的代码吗? (int*) getMaze{} 不是函数原型。应该是(int*) getMaze(){}

标签: objective-c c


【解决方案1】:

在C语言中,如果你需要从一个函数返回一个数组,你需要使用malloc为其分配内存,然后返回指向新分配内存的指针。

使用完此内存后,您需要free它。

类似:

#include <stdlib.h> /* need this include at top for malloc and free */

int* foo(int size)
{
    int* out = malloc(sizeof(int) * size); /* need to get the size of the int type and multiply it 
                                            * by the number of integers we would like to return */

    return out; /* returning pointer to the function calling foo(). 
                 * Don't forget to free the memory allocated with malloc */
}

int main()
{
    ... /* some code here */

    int* int_ptr = foo(25); /* int_ptr now points to the memory allocated in foo */

    ... /* some more code */

    free(int_ptr); /* we're done with this, let's free it */

    ...

    return 0;
}

这是 C 风格的 :) 在 Objective C 中可能还有其他(可以说更合适的)方法来做到这一点。但是,由于 Objective C 被认为是 C 的严格超集,这也可以工作。

如果我可以通过指针进一步扩展需要这样做。在函数中分配的 C 样式数组被视为 local,一旦函数超出范围,它们就会被自动清理。

正如另一张海报所指出的,从函数返回标准数组(例如int arr[10];)是一个坏主意,因为当数组返回时它不再存在。

在 C 中,我们通过使用 malloc 动态分配内存并返回指向该内存的指针来解决此问题。

但是,除非您充分释放此内存,否则您可能会引入内存泄漏或其他一些令人讨厌的行为(例如,free-ing malloc-ed 指针两次将产生 unwanted results)。

【讨论】:

  • 这很可能会导致内存泄漏,我们希望尽可能避免手动管理内存
  • 同意,我希望明确表示这只是 C 语言,Objective C 可能有更好的方法来做到这一点:)
【解决方案2】:

鉴于您明确询问 C 样式数组,这里没有建议您应该使用 NSArray 等。

不能直接返回一个C风格的数组(见下文)作为Objective-C(或C或C++)中的一个值,你可以返回一个引用这样的数组。

intdoublestruct x 等类型都可以按值传递 - 即代表值的实际位被传递。其他事情;比如C风格的数组、动态分配的内存、Objective-C风格的对象等;都通过引用传递 - 这是对内存中某个位置的引用,该位置包含表示值被传递的实际位。

因此,要从函数/方法返回 C 样式数组,您可以:

  1. 动态(mallocet al)一个数组并返回对分配内存的引用;
  2. 传递 in 对现有数组的引用并让函数填充它;或
  3. 将数组包装为struct...

通常的选择是 (1) 或 (2) - 请注意,您不能返回对堆栈分配数组的引用,如下所示:

int *thisIsInvalid()
{
   int myValues[5];
   ...
   return myValues; // will not work, the type is correct but once function
                    // returns myValues no longer exists.
}

如果您真的想按值返回一个(小)数组,您实际上可以使用 (3) 来实现。请记住,struct 值是按值传递的。所以以下将起作用:

typedef struct
{
   int array[5];
} fiveInts;

fiveInts thisIsValid()
{
   fiveInts myValues;
   ...
   myValues.array[3] = ...; // etc.
   ...
   return myValues;
}

(请注意,在读取/写入数组时,将数组包装在 struct 中没有开销 - 上面的成本是将所有值复制回来 - 因此只建议用于小型数组!)

HTH

【讨论】:

    【解决方案3】:
    - (NSArray *)toArray:(int *)maze {
       NSMutableArray *retVal = [[NSMutableArray alloc] init];
       for (int c = 0; maze[c] != NULL; c++) {
          [retVal addObject:[NSNumber numberWithInt:maze[c]]];
       }
       return [retVal array];
    }
    

    我从来都不习惯将可变数据传入和传出方法,但不知道为什么。如果您稍后需要更改这些值,请向数组发送 mutableCopy 消息。

    【讨论】:

      【解决方案4】:

      你可以这样做

      - (void)getArray:(int *)array withLength:(NSUInteger)length{
          for (int i = 0; i < length; i++)
              array[i] = i;
      }
      
      int array[3];
      [object getArray:array withLength:3];
      NSLog(@"%d %d %d", array[0], array[1], array[2]);  // 1 2 3
      

      【讨论】:

      • 我很确定您的第一个代码示例有问题。你不能返回一个数组,因为它会衰减为一个指向即将被弹出的堆栈帧的指针。
      • @Chuck 不,你错了。我检查了汇编代码,发现它使用objc_msgSend_stret,这意味着数组被视为结构。或者如果你认为我错了,你知道真相,你可以回答我的问题stackoverflow.com/questions/16709923/return-fixed-size-array
      • @xlc - 抱歉 Chuck 是正确的。我没有看到你的问题,所有人都没有回答。我已经为你添加了答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-17
      • 2011-10-21
      • 1970-01-01
      • 2013-10-26
      • 2021-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多