为什么你会使用的三操作员没有分配一个值为"真实"条件(x=x?:1)
-
25-09-2019 - |
题
在开放源码这码我跑过这一行代码:
machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */
这只是一个混乱的方式说:
if (machine->max_cpus) {
; //do nothing
} else {
machine->max_cpus = 1;
}
如果是这样,那岂不是更加清晰:
if (machine->max_cpus == 0) machine->max_cpus = 1;
有趣的是,这种编纂工作和现有海湾合作委员会,但不会汇编上 http://www.comeaucomputing.com/tryitout/ .
解决方案
这是在GNU允许如一个晦涩延伸到C
5.7条件句省略操作数
在条件的中间操作数 表达可被省略。然后,如果 第一操作数非零,它的值是 条件的值 表达
因此,表达
x ? : y
具有x的值,如果这是非零; 否则,y的值。
此例子完全等价 到
x ? x : y
在这个简单的例子中,能够 省略中间操作数不 特别有用。当它成为 有用是当第一操作数确实, 或者可以(如果它是一个宏参数), 包含的副作用。然后重复 在中间操作数将 执行两次副作用。 省略中间操作数使用 值已经计算无 重新计算它的不期望的效果。
正如你可能已经猜到,避免这种建议的可读性和可移植性的原因。我惊讶诚实看到这样的语法不兼容的扩展C.
其他提示
这是一个 GCC扩展程序,意思是“如果条件为真,则使用它,否则使用该其他值”,所以
machine->max_cpus = machine->max_cpus ?: 1;
为简写
machine->max_cpus = machine->max_cpus ? machine->max_cpus : 1;
虽然如果条件有副作用,它将只运行一次
使用GCC的-pedantic标志,它说
foo.c的:5:警告:ISO C不允许 省略的中间项? 表达
这是一个 GCC扩展和它变得更有趣的和有用的,当条件有副作用。
在这种情况下,是的,我一会同意它的晦涩比什么都重要。
在K&R BNF显示之间需要表达式 “?”和 “:”。我并不认为海合会应编译,没有一个诊断。
还有另外一个有用的情况下,对于这种--消除中间变量时调用一个功能或方法可能会返回nil,我们希望避免调用的两倍。例如(目标-C),假设我们要解开一个文件阵列,如果它存在,否则返回的一个空阵列。
- (NSArray*)hydrateBacklogFromFile:(NSString *path)
{
NSArray *backlog = @[];
NSData *backlogData = [NSData dataWithContentsOfFile:path];
if (backlogData)
{
backlog = [NSKeyedUnarchiver unarchiveObjectWithData:backlogData] ?: backlog;
}
return backlog;
}
该方案是较为简洁。
- (NSArray*)hydrateBacklogFromFile:(NSString *path)
{
NSArray *backlog = @[];
NSData *backlogData = [NSData dataWithContentsOfFile:path];
if (backlogData)
{
NSArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithData:backlogData];
if (tempArray != nil)
{
backlog = tempArray;
}
}
return backlog;
}
或丑陋的多返回等。
- (NSArray*)hydrateBacklogFromFile:(NSString *path)
{
NSData *backlogData = [NSData dataWithContentsOfFile:path];
if (backlogData)
{
NSArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithData:backlogData];
if (tempArray != nil)
{
return tempArray;
}
}
return @[];
}
所以它是非常有用的语法糖,我觉相当的可读性。缺点是
隐性转换的一个指bool。这是一个长期C 《公约》,但是大多数现代语言禁止它,复杂 任何移植的努力。
正如其他人所说它也是一个非标准的扩展,所以它应该 可以避免的,如果可移植性是一个考虑因素。