C 逗号运算符的使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1613230/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Uses of C comma operator
提问by pythonic metaphor
You see it used in for loop statements, but it's legal syntax anywhere. What uses have you found for it elsewhere, if any?
您会在 for 循环语句中看到它,但它在任何地方都是合法的语法。如果有的话,您在其他地方发现它有什么用途?
回答by AnT
C language (as well as C++) is historically a mix of two completely different programming styles, which one can refer to as "statement programming" and "expression programming". As you know, every procedural programming language normally supports such fundamental constructs as sequencingand branching(see Structured Programming). These fundamental constructs are present in C/C++ languages in two forms: one for statement programming, another for expression programming.
C 语言(以及 C++)在历史上是两种完全不同的编程风格的混合,可以将其称为“语句编程”和“表达式编程”。如您所知,每种过程式编程语言通常都支持诸如排序和分支之类的基本结构(请参阅结构化编程)。这些基本结构以两种形式出现在 C/C++ 语言中:一种用于语句编程,另一种用于表达式编程。
For example, when you write your program in terms of statements, you might use a sequence of statements separated by ;
. When you want to do some branching, you use if
statements. You can also use cycles and other kinds of control transfer statements.
例如,当您根据语句编写程序时,您可能会使用由;
. 当你想做一些分支时,你使用if
语句。您还可以使用循环和其他类型的控制转移语句。
In expression programming the same constructs are available to you as well. This is actually where ,
operator comes into play. Operator ,
in nothing else than a separator of sequential expressions in C, i.e. operator ,
in expression programming serves the same role as ;
does in statement programming. Branching in expression programming is done through ?:
operator and, alternatively, through short-circuit evaluation properties of &&
and ||
operators. (Expression programming has no cycles though. And to replace them with recursion you'd have to apply statement programming.)
在表达式编程中,您也可以使用相同的构造。这实际上是,
运营商发挥作用的地方。运算符,
只不过是 C 中顺序表达式的分隔符,即,
表达式编程中的运算符与语句编程中的作用相同;
。表达式编程中的分支是通过?:
运算符完成的,或者,通过&&
和||
运算符的短路评估属性完成。(不过,表达式编程没有循环。要用递归替换它们,您必须应用语句编程。)
For example, the following code
例如,下面的代码
a = rand();
++a;
b = rand();
c = a + b / 2;
if (a < c - 5)
d = a;
else
d = b;
which is an example of traditional statement programming, can be re-written in terms of expression programming as
这是传统语句编程的一个例子,可以在表达式编程方面重写为
a = rand(), ++a, b = rand(), c = a + b / 2, a < c - 5 ? d = a : d = b;
or as
或作为
a = rand(), ++a, b = rand(), c = a + b / 2, d = a < c - 5 ? a : b;
or
或者
d = (a = rand(), ++a, b = rand(), c = a + b / 2, a < c - 5 ? a : b);
or
或者
a = rand(), ++a, b = rand(), c = a + b / 2, (a < c - 5 && (d = a, 1)) || (d = b);
Needless to say, in practice statement programming usually produces much more readable C/C++ code, so we normally use expression programming in very well measured and restricted amounts. But in many cases it comes handy. And the line between what is acceptable and what is not is to a large degree a matter of personal preference and the ability to recognize and read established idioms.
毋庸置疑,在实践中,语句编程通常会生成更具可读性的 C/C++ 代码,因此我们通常会以非常精确和有限的数量使用表达式编程。但在很多情况下它会派上用场。可接受和不可接受之间的界限在很大程度上取决于个人喜好以及识别和阅读既定习语的能力。
As an additional note: the very design of the language is obviously tailored towards statements. Statements can freely invoke expressions, but expressions can't invoke statements (aside from calling pre-defined functions). This situation is changed in a rather interesting way in GCC compiler, which supports so called "statement expressions"as an extension (symmetrical to "expression statements" in standard C). "Statement expressions" allow user to directly insert statement-based code into expressions, just like they can insert expression-based code into statements in standard C.
作为附加说明:该语言的设计显然是针对语句量身定制的。语句可以自由调用表达式,但表达式不能调用语句(调用预定义函数除外)。这种情况在 GCC 编译器中以一种相当有趣的方式改变,它支持所谓的“语句表达式”作为扩展(与标准 C 中的“表达式语句”对称)。“语句表达式”允许用户直接将基于语句的代码插入到表达式中,就像他们可以将基于表达式的代码插入到标准 C 中的语句中一样。
As another additional note: in C++ language functor-based programming plays an important role, which can be seen as another form of "expression programming". According to the current trends in C++ design, it might be considered preferable over traditional statement programming in many situations.
另一个补充说明:在 C++ 语言中,基于函子的编程起着重要的作用,可以看作是另一种形式的“表达式编程”。根据 C++ 设计的当前趋势,在许多情况下,它可能被认为优于传统的语句编程。
回答by Hyman Lloyd
I think generally C's comma is not a good style to use simply because it's so very very easy to miss - either by someone else trying to read/understand/fix your code, or you yourself a month down the line. Outside of variable declarations and for loops, of course, where it is idiomatic.
我认为一般来说,C 的逗号不是一个很好的使用风格,因为它很容易被遗漏 - 要么是其他人试图阅读/理解/修复您的代码,要么是您自己一个月后。在变量声明和 for 循环之外,当然,这是惯用的。
You can use it, for example, to pack multiple statements into a ternary operator (?:), ala:
例如,您可以使用它来将多个语句打包到一个三元运算符 (?:) 中,ala:
int x = some_bool ? printf("WTF"), 5 : fprintf(stderr, "No, really, WTF"), 117;
but my gods, why?!? (I've seen it used in this way in real code, but don't have access to it to show unfortunately)
但我的天,为什么?!?(我已经看到它在实际代码中以这种方式使用,但不幸的是无法访问它以显示)
回答by Adisak
I've seen it used in macros where the macro is pretending to be a function and wants to return a value but needs to do some other work first. It's always ugly and often looks like a dangerous hack though.
我已经看到它在宏中使用,其中宏伪装成一个函数并想要返回一个值但需要先做一些其他工作。它总是丑陋的,但通常看起来像一个危险的黑客。
Simplified example:
简化示例:
#define SomeMacro(A) ( DoWork(A), Permute(A) )
Here B=SomeMacro(A)
"returns" the result of Permute(A) and assigns it to "B".
这里B=SomeMacro(A)
“返回”Permute(A) 的结果并将其分配给“B”。
回答by P Shved
Two killer comma operator features in C++:
C++ 中的两个杀手级逗号运算符功能:
a) Read from stream until specific string is encountered (helps to keep the code DRY):
a) 从流中读取直到遇到特定字符串(有助于保持代码干燥):
while (cin >> str, str != "STOP") {
//process str
}
b) Write complex code in constructor initializers:
b) 在构造函数初始值设定项中编写复杂代码:
class X : public A {
X() : A( (global_function(), global_result) ) {};
};
回答by Stjepan Rajko
The Boost Assignmentlibrary is a good example of overloading the comma operator in a useful, readable way. For example:
所述升压分配库是在一个有用的,可读的方式重载逗号操作符的一个很好的例子。例如:
using namespace boost::assign;
vector<int> v;
v += 1,2,3,4,5,6,7,8,9;
回答by fa.
I had to use a comma to debug mutex locks to put a message beforethe lock starts to wait.
我不得不使用逗号来调试互斥锁,以便在锁开始等待之前放置一条消息。
I could not but the log message in the body of the derived lock constructor, so I had to put it in the arguments of the base class constructor using : baseclass( ( log( "message" ) , actual_arg )) in the initialization list. Note the extra parenthesis.
我不得不将日志消息放在派生锁构造函数的主体中,因此我不得不使用初始化列表中的 baseclass( ( ( log( "message" ) , actual_arg )) 将其放入基类构造函数的参数中。注意额外的括号。
Here is an extract of the classes :
这是类的摘录:
class NamedMutex : public boost::timed_mutex
{
public:
...
private:
std::string name_ ;
};
void log( NamedMutex & ref__ , std::string const& name__ )
{
LOG( name__ << " waits for " << ref__.name_ );
}
class NamedUniqueLock : public boost::unique_lock< NamedMutex >
{
public:
NamedUniqueLock::NamedUniqueLock(
NamedMutex & ref__ ,
std::string const& name__ ,
size_t const& nbmilliseconds )
:
boost::unique_lock< NamedMutex >( ( log( ref__ , name__ ) , ref__ ) ,
boost::get_system_time() + boost::posix_time::milliseconds( nbmilliseconds ) ),
ref_( ref__ ),
name_( name__ )
{
}
....
};
回答by fa.
From the C standard:
从 C 标准:
The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its evaluation. Then the right operand is evaluated; the result has its type and value. (A comma operator does not yield an lvalue.)) If an attempt is made to modify the result of a comma operator or to access it after the next sequence point, the behavior is undefined.
逗号运算符的左操作数被计算为空表达式;评估后有一个序列点。然后评估正确的操作数;结果有其类型和值。(逗号运算符不产生左值。))如果尝试修改逗号运算符的结果或在下一个序列点之后访问它,则行为未定义。
In short it let you specify more than one expression where C expects only one. But in practice it's mostly used in for loops.
简而言之,它允许您指定多个表达式,而 C 只需要一个表达式。但实际上它主要用于 for 循环。
Note that:
注意:
int a, b, c;
is NOT the comma operator, it's a list of declarators.
不是逗号运算符,它是声明符列表。
回答by SadSido
You can overload it (as long as this question has a "C++" tag). I have seen some code, where overloaded comma was used for generating matrices. Or vectors, I don't remember exactly. Isn't it pretty (although a little confusing):
你可以重载它(只要这个问题有一个“C++”标签)。我看过一些代码,其中重载逗号用于生成矩阵。或者向量,我记不太清楚了。是不是很漂亮(虽然有点混乱):
MyVector foo = 2, 3, 4, 5, 6;
MyVector foo = 2, 3, 4, 5, 6;
回答by Thomas Padron-McCarthy
It is sometimes used in macros, such as debug macros like this:
它有时用于宏,例如像这样的调试宏:
#define malloc(size) (printf("malloc(%d)\n", (int)(size)), malloc((size)))
(But look at this horrible failure, by yours truly, for what can happen when you overdo it.)
(但看看这个可怕的失败,你真的,因为如果你做得太多会发生什么。)
But unless you really need it, or you are sure that it makes the code more readable and maintainable, I would recommend against using the comma operator.
但是除非您真的需要它,或者您确定它使代码更具可读性和可维护性,否则我建议不要使用逗号运算符。
回答by jmucchiello
Outside of a for loop, and even there is has can have an aroma of code smell, the only place I've seen as a good use for the comma operator is as part of a delete:
在 for 循环之外,即使有 has 也可能有代码气味,我认为逗号运算符的唯一用途是作为删除的一部分:
delete p, p = 0;
The only value over the alternative is you can accidently copy/paste only half of this operation if it is on two lines.
替代方案的唯一价值是如果它在两行上,您可能会意外地复制/粘贴此操作的一半。
I also like it because if you do it out of habit, you'll never forget the zero assignment. (Of course, why p isn't inside somekind of auto_ptr, smart_ptr, shared_ptr, etc wrapper is a different question.)
我也喜欢它,因为如果您出于习惯这样做,您将永远不会忘记零分配。(当然,为什么 p 不在某种 auto_ptr、smart_ptr、shared_ptr 等包装器中是一个不同的问题。)