如何创建一个基于堆栈的字符数组,可以通过块闭包捕获(const复制)?

时间:2013-03-23 15:01:48

标签: objective-c-blocks

我正在试图找出一种干净的方法来创建一个基于堆栈的C字符串(即char []),可以通过块闭包捕获(通过const副本)。基本想法是这样的:

char myString[16] = {0};
// ... put something into myString.
dispatch_block_t block = ^(){
    const size_t len = strlen(myString);
    if (len)
        NSLog(@"Not zero length");
};

但这样做会导致编译器抱怨:

error: cannot refer to declaration with an array type inside block

我发现我可以将char数组放入结构中,但这看起来有点难看。还有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

堆栈分配的问题是,一旦离开函数,堆栈帧就会消失,但块代码仍然存在,并且可能引用该堆栈帧中的变量。块通过分配和复制它所引用的所有值(包括用__block声明的变量)来处理它。从理论上讲,它们应该能够复制静态大小的阵列,但出于某种原因,它不受支持。请注意,很可能是我不知道与阵列相关的技术问题。

所以我看到的最简单的解决方案是使用malloc / free:

char *myString = calloc(16,1);

dispatch_block_t block = ^(){
    const size_t len = strlen(myString);
    if (len)
        NSLog(@"Not zero length");
    free(myString);
};

只要您不需要多次重复使用该块,就可以了。如果你需要重新使用这个块,那么将myString包装在一个NSData对象中,你可以在你的块中引用它并摆脱它。

char *myString = calloc(16,1);
NSData *myStringData = [NSData dataWithBytesNoCopy:myString length:16 freeWhenDone:YES];

dispatch_block_t block = ^(){
    const char *myString = myStringData.bytes;
    const size_t len = strlen(myString);
    if (len)
        NSLog(@"Not zero length");
};

答案 1 :(得分:0)

在这一刻已经过了一个星期,我开始有信心没有一些我只是遗漏的魔法语法。为了未来访客的利益,这是迄今为止我发现的最好的方式来实现我在这里所要求的:

    typedef struct { char string[32]; } StackString;

    StackString foo = {0};
    strcpy(foo.string, "foo");

    dispatch_block_t block = ^(){
        StackString blockFoo = foo;
        NSLog(@"Block String: %s", blockFoo.string);
    };

    for (int i = 0; i < 5; ++i)
    {
        sprintf(foo.string, "i = %d", i);
        NSLog(@"Loop string: %s", foo.string);
        block();
    }

其输出为:

2013-03-31 11:30:52.778 TestClosure[98968:303] Loop string: i = 0
2013-03-31 11:30:52.780 TestClosure[98968:303] Block String: foo
2013-03-31 11:30:52.780 TestClosure[98968:303] Loop string: i = 1
2013-03-31 11:30:52.780 TestClosure[98968:303] Block String: foo
2013-03-31 11:30:52.780 TestClosure[98968:303] Loop string: i = 2
2013-03-31 11:30:52.781 TestClosure[98968:303] Block String: foo
2013-03-31 11:30:52.781 TestClosure[98968:303] Loop string: i = 3
2013-03-31 11:30:52.782 TestClosure[98968:303] Block String: foo
2013-03-31 11:30:52.782 TestClosure[98968:303] Loop string: i = 4
2013-03-31 11:30:52.782 TestClosure[98968:303] Block String: foo

这让我觉得包裹在一个struct中,固定大小的数组被const复制到块闭包中就好了。