Uses of C comma operator [duplicate]

2018-12-31 14:56发布

This question already has an answer here:

You see it used in for loop statements, but it's legal syntax anywhere. What uses have you found for it elsewhere, if any?

20条回答
旧人旧事旧时光
2楼-- · 2018-12-31 15:40

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.

You can use it, for example, to pack multiple statements into a ternary operator (?:), 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)

查看更多
回忆,回不去的记忆
3楼-- · 2018-12-31 15:40

It's very useful in adding some commentary into ASSERT macros:

ASSERT(("This value must be true.", x));

Since most assert style macros will output the entire text of their argument, this adds an extra bit of useful information into the assertion.

查看更多
后来的你喜欢了谁
4楼-- · 2018-12-31 15:43

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 sequencing and branching (see Structured Programming). These fundamental constructs are present in C/C++ languages in two forms: one for statement programming, another for expression programming.

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.

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.)

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.

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.

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.

查看更多
姐姐魅力值爆表
5楼-- · 2018-12-31 15:44

I've used it for a macro to "assign a value of any type to an output buffer pointed to by a char*, and then increment the pointer by the required number of bytes", like this:

#define ASSIGN_INCR(p, val, type)  ((*((type) *)(p) = (val)), (p) += sizeof(type))

Using the comma operator means the macro can be used in expressions or as statements as desired:

if (need_to_output_short)
    ASSIGN_INCR(ptr, short_value, short);

latest_pos = ASSIGN_INCR(ptr, int_value, int);

send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));

It reduced some repetitive typing but you do have to be careful it doesn't get too unreadable.

Please see my overly-long version of this answer here.

查看更多
栀子花@的思念
6楼-- · 2018-12-31 15:45

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.

查看更多
ら面具成の殇う
7楼-- · 2018-12-31 15:47

Found it in array initialization:

In C what exactly happens if i use () to initialize a double dimension array instead of the {}?

When I initialize an array a[][]:

int a[2][5]={(8,9,7,67,11),(7,8,9,199,89)};

and then display the array elements.

I get:

11 89 0 0 0 
0 0 0 0 0
查看更多
登录 后发表回答