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



我试图找出一个干净的方法来创建一个基于堆栈的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

我想到,我可以把字符数组放入一个结构体,但这看起来有点丑。有没有更好的办法?

堆栈分配的问题是,一旦离开函数,堆栈帧就会消失,但是块代码仍然存在,并且可能引用该堆栈帧中的变量。block通过分配和复制它引用的所有值到堆来处理这个问题,包括用__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对象中,你可以在你的块中引用这个对象,并去掉free.

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");
};

到这里已经一周了,我开始确信没有什么神奇的语法是我所遗漏的。为了将来的访问者的利益,这是迄今为止我发现的实现我在这里所要求的最好的方法:

    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

这使我相信,在结构体中包装,固定大小的数组被const复制到块闭包中就可以了。

相关内容

最新更新