关于在Objective-C中没有主体的"for"循环的奇怪的编译器优化/行为

Avi*_*ron 2 c arrays compiler-construction for-loop objective-c

我有以下C数组NSString *:

static NSString *const OrderByValueNames[] = {@"None",@"Added",@"Views",@"Rating",@"ABC",@"Meta"};
Run Code Online (Sandbox Code Playgroud)

现在,我想在运行时检查这个数组的长度,所以我编写了以下方法:

NSInteger LengthOfArray(NSString *const array[])
{
    NSInteger length = 0;
    // For Loop Without a body!
    for (length = 0; array[length] != nil; length++);
    return length;
}
Run Code Online (Sandbox Code Playgroud)

现在,当我在debug配置中运行此代码时,一切都很好,函数返回正确的结果.

但是一旦我切换到release配置并再次运行它,程序就会在for循环中冻结.在执行循环10秒后,iOS会杀死应用程序以便不响应.奇怪的.

现在,如果我将循环添加到循环中,就像这样:

for (length = 0; array[length] != nil; length++)
{
    NSLog(@"%d",length);
}
Run Code Online (Sandbox Code Playgroud)

然后即使在发布模式下也能正常工作.

给循环一个空体,就像那样:

for (length = 0; array[length] != nil; length++){}
Run Code Online (Sandbox Code Playgroud)

在发布模式下仍然冻结.

我的猜测是在发布模式下运行时有一个编译器优化,但具体到底是什么?!

有任何想法吗?

Gra*_*and 10

默认情况下,C风格的数组不是终止的.如果要以这种方式检查长度,则需要自己添加终结器.

static NSString *const OrderByValueNames[] =
   {@"None",@"Added",@"Views",@"Rating",@"ABC",@"Meta",nil};
Run Code Online (Sandbox Code Playgroud)

找到长度的更好方法就是:

length = sizeof(OrderByValueNames) / sizeof(OrderByValueNames[0]);
Run Code Online (Sandbox Code Playgroud)

(请注意,如果将数组传递给函数,则此技巧不起作用,因为它会退化为指针.)

  • 走出数组的末尾是**未定义的行为**.这意味着任何事情都可能发生.所以无论发生什么都在标准的范围内. (3认同)

pmd*_*mdj 6

您的OrderByValueNames数组不包含nil元素.难怪你找不到一个!像这样走出数组的末尾将导致未定义的行为.如果要标记数组的末尾,则nil必须手动添加它.

顺便说一句,如果你想知道固定大小的C数组的长度,你可以这样做:

length = sizeof(OrderByValueNames)/sizeof(OrderByValueNames[0]);
Run Code Online (Sandbox Code Playgroud)

但这不适用于函数参数,因为它们只是指针!