0

我试图找出一种干净的方法来创建一个基于堆栈的 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 数组放入一个结构中,但这看起来有点难看。有没有更好的办法?

4

2 回答 2

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");
};
于 2013-03-31T11:49:53.390 回答
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

这让我相信,包装在一个结构中,固定大小的数组被 const 复制到块闭包中就好了。

于 2013-03-31T16:45:45.427 回答