Vik*_*r S 79 c c++ boolean ternary-operator
我正在为嵌入式项目使用SDK.在这个源代码中,我发现了一些代码,至少我发现这些代码很奇怪.在SDK的许多地方都有这种格式的源代码:
#define ATCI_IS_LOWER( alpha_char ) ( ( (alpha_char >= ATCI_char_a) && (alpha_char <= ATCI_char_z) ) ? 1 : 0 )
#define ATCI_IS_UPPER( alpha_char ) ( ( (alpha_char >= ATCI_CHAR_A) && (alpha_char <= ATCI_CHAR_Z) ) ? 1 : 0 )
Run Code Online (Sandbox Code Playgroud)
这里使用三元运算符有什么不同吗?
是不是
#define FOO (1 > 0)
Run Code Online (Sandbox Code Playgroud)
同样的
#define BAR ( (1 > 0) ? 1 : 0)
Run Code Online (Sandbox Code Playgroud)
?
我尝试使用它来评估它
printf("%d", FOO == BAR);
Run Code Online (Sandbox Code Playgroud)
得到结果1,所以看起来它们是平等的.是否有理由像他们一样编写代码?
Bat*_*eba 131
你是对的,在C中它是同义的.无论您的特定三元条件和 (1 > 0)
有型int
.
但是在C++中,在一些奇怪的极端情况下(例如作为重载函数的参数),这很重要,因为你的三元条件表达式是类型int
,而(1 > 0)
类型bool
.
我的猜测是作者已经考虑到这一点,着眼于保持C++兼容性.
unw*_*ind 28
有一些linting工具认为比较结果是布尔值,不能直接用于算术.
不是命名或指向任何手指,但PC-lint是这样的linting工具.
我不是说他们是对的,但这可能解释为什么代码是这样编写的.
zwo*_*wol 19
你有时会在非常古老的代码中看到这一点,从之前有一个C标准拼写出(x > y)
评估为数字1或0; 一些CPU宁愿将其评估为-1或0,而一些非常古老的编译器可能只是跟随,因此一些程序员认为他们需要额外的防御性.
有时你会也看到这一点,因为类似的表述并不一定计算为数字1或0.例如,在
#define GRENFELZ_P(flags) (((flags) & F_DO_GRENFELZ) ? 1 : 0)
Run Code Online (Sandbox Code Playgroud)
内部&
表达式的计算结果为0或数值F_DO_GRENFELZ
,可能不是 1,因此使用? 1 : 0
它来规范化它.我个人认为将其写为更清楚
#define GRENFELZ_P(flags) (((flags) & F_DO_GRENFELZ) != 0)
Run Code Online (Sandbox Code Playgroud)
但合理的人可以不同意.如果你连续测试了大量这些,测试不同类型的表达式,有人可能已经决定将所有这些表达式放在? 1 : 0
最后,而不是担心实际需要它们.
Kon*_*hog 15
SDK代码中存在一个错误,三元可能是修复它的一个障碍.
作为一个宏,参数(alpha_char)可以是任何表达式,并且应该用括号括起来,因为诸如'A'&&'c'之类的表达式将无法通过测试.
#define IS_LOWER( x ) ( ( (x >= 'a') && (x <= 'z') ) ? 1 : 0 )
std::cout << IS_LOWER('A' && 'c');
**1**
std::cout << IS_LOWER('c' && 'A');
**0**
Run Code Online (Sandbox Code Playgroud)
这就是为什么人们应该总是在扩展中括起宏参数.
所以在你的例子中(但有参数),这些都是错误的.
#define FOO(x) (x > 0)
#define BAR(x) ((x > 0) ? 1 : 0)
Run Code Online (Sandbox Code Playgroud)
他们最正确地被替换为
#define BIM(x) ((x) > 0)
Run Code Online (Sandbox Code Playgroud)
@CiaPan在以下评论中提出了一个很好的观点,即多次使用参数会导致无法确定的结果.例如
#define IS_LOWER( x ) (((x) >= 'a') && ((x) <= 'z'))
char ch = 'y';
std::cout << IS_LOWER(ch++);
**1**
**BUT ch is now '{'**
Run Code Online (Sandbox Code Playgroud)
在C中没关系.C中的布尔表达式具有类型int
和值为0
或者1
,因此
ConditionalExpr ? 1 : 0
Run Code Online (Sandbox Code Playgroud)
没有效果.
在C++中,它实际上是一个强制转换int
,因为C++中的条件表达式具有类型bool
.
#include <stdio.h>
#include <stdbool.h>
#ifndef __cplusplus
#define print_type(X) _Generic(X, int: puts("int"), bool: puts("bool") );
#else
template<class T>
int print_type(T const& x);
template<> int print_type<>(int const& x) { return puts("int"); }
template<> int print_type<>(bool const& x) { return puts("bool"); }
#endif
int main()
{
print_type(1);
print_type(1 > 0);
print_type(1 > 0 ? 1 : 0);
/*c++ output:
int
int
int
cc output:
int
bool
int
*/
}
Run Code Online (Sandbox Code Playgroud)
它也可能没有效果,作者只是认为它使代码更清晰.
一个简单的解释是,有些人要么不理解条件会在C中返回相同的值,要么他们认为写入更清晰((a>b)?1:0)
.
这就解释了为什么有些人也会在具有适当布尔值的语言中使用类似的结构,这在C语法中就是如此(a>b)?true:false)
.
这也解释了为什么你不应该不必要地改变这个宏.