int a = 0;
NSDictionary* d = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:a], @"A",
[NSNumber numberWithInt:a+=1], @"B",
[NSNumber numberWithInt:a+=1], @"C",
nil];
NSLog(@"%@", d);
iPad上的结果:
{ A = 0; B = 1; C = 2; }
iOS模拟器中的结果:
{ A = 2; B = 2; C = 1; }
任何人都可以重现结果,甚至更好地解释一下吗?
答案 0 :(得分:8)
这是未定义的行为。这些价值观没有正确的答案。在序列点之间未定义应用效果的顺序,并且参数列表中的逗号不是序列点。
答案 1 :(得分:6)
函数或方法的参数的评估顺序是未定义的,并由编译器确定。这意味着无法保证第一个数字将在第二个数字之前创建,并且由c的objective-c继承。看起来在iPad上,它们的执行顺序与它们在代码中的顺序相同,但对于模拟器,它们是以相反的顺序创建的。这是事件的顺序:
ipad公司:
a
。使用其当前值(0)。a += 1
。递增a
并返回其新值(1)。a += 1
。递增a
并返回其新值(2)。模拟器:
a += 1
。递增a
并返回其新值(1)。a += 1
。递增a
并返回其新值(2)。a
。使用其当前值(2)。由于模拟器使用的i386的调用约定是参数以相反的顺序在堆栈上传递,我猜这就是编译器以相反的顺序对它们进行求值的原因。
要解决您的问题,您应该在创建字典之前创建NSNumber对象,强制编译器使用您想要的顺序。
int a = 0;
NSNumber *numA = [[NSNumber alloc] initWithInt:a];
a += 1;
NSNumber *numB = [[NSNumber alloc] initWithInt:a];
a += 1;
NSNumber *numC = [[NSNumber alloc] initWithInt:a];
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:numA, @"A", numB ,@"B", numC, @"C", nil];
[numA release];
[numB release];
[numC release];
NSLog(@"%@", d);