考虑一个 C 变体,其中比较运算符 return 所有位都设置为真值,0 为假
Consider a C variant, where comparison operators return all bits set for true values and 0 for false
我在看一道题,看不出怎么会偏离正常的C。在C中,1代表true(当然任何非零值也被认为是true),0代表false .如果我们改为返回条件评估为真时设置的所有位,在什么情况下 C 变体会偏离传统 C。对我来说似乎是一样的,但我知道一定有一个方面我没有考虑,或者只是没有以正确的方式思考这个问题。非常感谢正确方向的提示。
一个优点是可以更容易地编写名义上无分支的选择:
// Select c or d based on comparison of a and b.
static int Select(int a, int b, int c, int d)
{
int mask = a < b;
return c & mask | d & ~mask;
}
在标准 C 中,这可以写成 return a < b ? c : d;
,但名义上涉及测试 a < b
,然后执行分支指令。分支指令通常会对处理器性能产生有害影响,我们力求在高性能代码中避免它们。所以有一个位掩码,可以用来在逻辑指令上进行选择,而不是分支,在某些情况下可能是有益的。
但是,像这样的问题是假设性的并且过时了。编译器可能会优化 a < b ? c : d
。或者,即使使用掩码更好,也存在编译器将如何生成它以实现 a < b
的问题——这本身可能涉及执行测试和执行分支指令,从而抵消了好处。所以像这样的问题一般孤立地没有很好的答案。它们仅在课堂环境中用于提示或描绘学生对 material.
的熟悉程度
"non-zero" 被认为 正确的原因 可能与底层 CPU 架构有关。大多数汇编语言通过比较设置相应 'zero flag' 的操作码(在 x86 上使用 cmp
指令,或者其他指令将隐式设置零标志)来实现条件控制流。然后条件分支指令将测试零标志并仅在设置时跳转到新位置。
仅当值为零时才设置零标志,因此它避免了额外的比较指令来检查值是否恰好等于一。
例如,在 x86 机器上:
int fn(int x)
{
if(x) return 1;
else return 0;
}
会变成(类似)这个:
fn:
cmp edi, 0
jz .L2
mov eax, 1
ret
.L2:
mov eax, 0
ret
假设您的问题是 "why does C treat non-zero values as true?"(我并不完全确定),那么原因是因为它是使用我们在现代硬件上拥有的指令集的最有效方式(据说,上面的例子是不必要的和低效的,但只是为了说明这一点)。
我在看一道题,看不出怎么会偏离正常的C。在C中,1代表true(当然任何非零值也被认为是true),0代表false .如果我们改为返回条件评估为真时设置的所有位,在什么情况下 C 变体会偏离传统 C。对我来说似乎是一样的,但我知道一定有一个方面我没有考虑,或者只是没有以正确的方式思考这个问题。非常感谢正确方向的提示。
一个优点是可以更容易地编写名义上无分支的选择:
// Select c or d based on comparison of a and b.
static int Select(int a, int b, int c, int d)
{
int mask = a < b;
return c & mask | d & ~mask;
}
在标准 C 中,这可以写成 return a < b ? c : d;
,但名义上涉及测试 a < b
,然后执行分支指令。分支指令通常会对处理器性能产生有害影响,我们力求在高性能代码中避免它们。所以有一个位掩码,可以用来在逻辑指令上进行选择,而不是分支,在某些情况下可能是有益的。
但是,像这样的问题是假设性的并且过时了。编译器可能会优化 a < b ? c : d
。或者,即使使用掩码更好,也存在编译器将如何生成它以实现 a < b
的问题——这本身可能涉及执行测试和执行分支指令,从而抵消了好处。所以像这样的问题一般孤立地没有很好的答案。它们仅在课堂环境中用于提示或描绘学生对 material.
"non-zero" 被认为 正确的原因 可能与底层 CPU 架构有关。大多数汇编语言通过比较设置相应 'zero flag' 的操作码(在 x86 上使用 cmp
指令,或者其他指令将隐式设置零标志)来实现条件控制流。然后条件分支指令将测试零标志并仅在设置时跳转到新位置。
仅当值为零时才设置零标志,因此它避免了额外的比较指令来检查值是否恰好等于一。
例如,在 x86 机器上:
int fn(int x)
{
if(x) return 1;
else return 0;
}
会变成(类似)这个:
fn:
cmp edi, 0
jz .L2
mov eax, 1
ret
.L2:
mov eax, 0
ret
假设您的问题是 "why does C treat non-zero values as true?"(我并不完全确定),那么原因是因为它是使用我们在现代硬件上拥有的指令集的最有效方式(据说,上面的例子是不必要的和低效的,但只是为了说明这一点)。