本文介绍了返回固定大小的数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时候我想要回东西数组,我知道我应该做的是让呼叫者进行阵列和修改法阵。但事实证明,这个工作的?

Sometimes I want to return an array of something, I know what I should do it let the caller to make the array and modify the array in the method. But it turns out this works?

@interface Test : NSObject
@end

@implementation Test

- (CGPoint[2])test {
    CGPoint p1 = {1, 2};
    CGPoint p2 = {3, 4};
    return (CGPoint[2]) {p1, p2};
}

- (int[2])test2 {
    int i = 1;
    int i2 = 2;
    return (int[2]){i, i2};
}

- (int[5])test3 {
    int i = 1;
    int i2 = 2;
    return (int[5]){i, i2, 3, 4, 5};
}

@end

@implementation testTests

- (void)testExample
{
    Test *t = [Test new];
    CGPoint p = [t test][0];
    CGPoint p2 = [t test][1];
    CGPoint *ps = [t test];
    CGPoint p3 = ps[0];
    CGPoint p4 = ps[1];
    NSLog(@"%@ %@ %@ %@", NSStringFromCGPoint(p), NSStringFromCGPoint(p2), NSStringFromCGPoint(p3), NSStringFromCGPoint(p4));
    // {1, 2} {3, 4} {1, 2} {3, 4}

    {
        Method m = class_getInstanceMethod([Test class], @selector(test));
        const char *rettype = method_copyReturnType(m);
        NSUInteger size = 0;
        NSGetSizeAndAlignment(rettype, &size, NULL);
        NSLog(@"%s %d", rettype, size); // [2{CGPoint=ff}] 16
    }

    {
        Method m = class_getInstanceMethod([Test class], @selector(test2));
        const char *rettype = method_copyReturnType(m);
        NSUInteger size = 0;
        NSGetSizeAndAlignment(rettype, &size, NULL);
        NSLog(@"%s %d", rettype, size); // [2i] 8
    }

    {
        Method m = class_getInstanceMethod([Test class], @selector(test3));
        const char *rettype = method_copyReturnType(m);
        NSUInteger size = 0;
        NSGetSizeAndAlignment(rettype, &size, NULL);
        NSLog(@"%s %d", rettype, size); // [5i] 20
    }
}

@end

所以看起来我可以返回的东西数组喜欢直接返回一个结构。由于 NSGetSizeAndAlignment 建议,返回值实际上是整个数组不只是一个指针。 (16 CGPoint [2] ,8 INT [2] 20 INT [5]

So it looks like I can return an array of something directly like return a struct. As NSGetSizeAndAlignment suggested, the return value is actually the whole array not just a pointer. (16 for CGPoint[2], 8 for int[2], 20 for int[5])

但实际使用返回的值,我只能做到这一点。

But to actually use the returned value, I can only do this

CGPoint *ps = [t test];

在这里 PS 只是一个指针。所以,问题是可以我安全返回数组这样吗?其中数组的,在分配?在被调用函数或调用函数的栈栈?诚然,整个阵列从被调用函数或类似结构的编译器复制分配自动调用函数数组?

and here ps is just a pointer. So the question is that can I safely return array like this? where is the array allocated at? In stack of callee function or in stack of caller function? Is true that whole array is copied from callee function or like struct the complier allocated the array in caller function automatically?

我用X code 4.6.2

I am using Xcode 4.6.2

更新

看起来像32位的应用程序,其中包括iOS应用(ARM)的iOS模拟器(86)和32位应用程序OSX这只铁锅。

Looks like this only woks for 32bits app, which includes iOS app (ARM), iOS simulator (x86) and 32bits OSX app.

推荐答案

C不支持返回一个数组。为什么这显然是对你的作品我不知道​​。我进了你code,补充缺少的方法/进口,固定格式的警告,调整第一的NSLog - 没有任何这改变了code中的任何显著方式 - 其结果是:

C does not support returning an array. Why this apparently works for you I've no idea. I entered your code, added the missing methods/imports, fixed the format warnings, tweaked the first NSLog - none of which changes the code in any significant way - and the result is:

p: {0.000000, 0.000000}
p2: {49923903424063506281151950574939686583391145211556805465272890158614887709849874883833083042335634395057539888815696938380880844447770099086084465717389090095104.000000, 5053651901346670085892443969395884608467030378650281488576308318306304.000000}
p3: {0.000000, 0.000000}
p4: {0.000000, 0.000000}

总之,垃圾 - 这是你所期望

In short, garbage - which is what you'd expect.

这是使用苹果LLVM编译器默认的10.8.4 X $ C $Ç4.6.2。切换到GCC-LLVM编译器和它甚至不会编译 - 错误的方法不能返回数组。为了完整还测试了C11语言选项(苹果LLVM) - 运行和产生的垃圾如上

That is with Xcode 4.6.2 on 10.8.4 using the Apple LLVM default compiler. Switch to the gcc-llvm compiler and it won't even compile - the error is methods cannot return arrays. For completeness also tested the C11 language options (Apple LLVM) - runs and produces garbage as above.

如果你真的需要按值传递数组,你可以使用一个简单的方法来做到这点:原始类型(整型,浮点等)的结构的都是由重视用C过去了,所以你可以通过它包装按值传递数组的结构

If you really need to pass arrays by value you can do this using a simple trick: primitive types (int, float, etc.) and structures are all passed by valued in C, so you can pass an array by value by wrapping it in a struct:

typedef struct
{
   CGPoint values[2];
} Array2;

@interface Test2 : NSObject
@end

@implementation Test2

- (Array2)test
{
   CGPoint p1 = {1, 2};
   CGPoint p2 = {3, 4};
   return (Array2) {{p1, p2}};
}


- (void)testExample
{
   Test2 *t = self;
   CGPoint p = [t test].values[0];
   CGPoint p2 = [t test].values[1];
   Array2 ps = [t test];
   CGPoint p3 = ps.values[0];
   CGPoint p4 = ps.values[1];
   NSLog(@"p: %@\np2: %@\np3: %@\np4: %@", NSStringFromCGPoint(p), NSStringFromCGPoint(p2), NSStringFromCGPoint(p3), NSStringFromCGPoint(p4));
}

@end

和本生产:

p: {1.000000, 2.000000}
p2: {3.000000, 4.000000}
p3: {1.000000, 2.000000}
p4: {3.000000, 4.000000}

因为它应该。

补遗 - 回应评论

C标准不允许数组(和函数)的回归 - 但阵列(和函数)引用是允许的。

The C Standard disallows the returning of arrays (and functions) - but references to arrays (and functions) are allowed.

有关功能参数,如果给定类型是阵列(或功能)类型则它被调整为是指参考阵列(或功能)。

For function parameters if the type given is an array (or function) type then it is adjusted to mean reference to array (or function).

虽然我不知道该标准规定它,一些编译器(如苹果4.2,而不是4.2 GCC)应用参数类型调整为返回类型,以及 - 所以你可以声明一个函数返回一个数组,它被调整到以一个阵列的引用。

Though I don't know that the Standard states it, some compilers (e.g. Apple 4.2, but not GCC 4.2) apply the parameter type adjustment to the return type as well - so you can declare a function to return an array and it is adjusted to be a reference to an array.

目标-C的元数据记录的声明的,而不是的调整的,类型。这就是为什么你看到调用 method_copyReturnType / NSGetSizeAndAlignment 当你这样做的结果。然而,编译是以下的标准,调整的类型,而不是由值返回阵列

Objective-C's metadata is recording the declared, rather than the adjusted, type. This is why you see the results you do when calling method_copyReturnType/NSGetSizeAndAlignment. However the compiling is following the standard, adjusting the type, and not returning arrays by value.

尽管如此编译器当然可以选择执行数组按值作为扩展 - 因为机械这样做需要存在支持结构按值反正。我不知道随便任何编译器是否支持这种扩展。我只测试了4.2英特尔编译器(苹果&安培; GCC)和他们没有(和GCC不支持声明的返回类型的数组或者,这是一个编译时错误)

Having said that a compiler could of course choose to implement array-by-value as an extension - as the machinery to do so needs to be there to support struct-by-value anyway. I don't know offhand whether any compiler supports such an extension. I have only tested the 4.2 Intel compilers (Apple & GCC) and they do not (and GCC does not support declaring the return type as an array either, that is a compile time error).

心连心

这篇关于返回固定大小的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 19:31