什么是,
经营者用C呢?
表达方式:
(expression1, expression2)
首先计算expression1,然后计算expression2,并为整个表达式返回expression2的值.
我见过最常用的while
循环:
string s; while(read_string(s), s.len() > 5) { //do something }
它会进行操作,然后根据副作用进行测试.另一种方式是这样做:
string s; read_string(s); while(s.len() > 5) { //do something read_string(s); }
该逗号操作将评估左操作数,丢弃的结果,然后计算右边的操作数,这将是这个结果.链接中提到的惯用法是在初始化for
循环中使用的变量时,它给出了以下示例:
void rev(char *s, size_t len) { char *first; for ( first = s, s += len - 1; s >= first; --s) /*^^^^^^^^^^^^^^^^^^^^^^^*/ putchar(*s); }
否则,不会有太多伟大的用途逗号操作符,虽然它很容易被滥用来生成代码是难以阅读和维护.
从草案C99标准来看,语法如下:
expression: assignment-expression expression , assignment-expression
和第2段说:
逗号运算符的左操作数被计算为void表达式; 评估后有一个序列点.然后评估右操作数; 结果有它的类型和价值. 97)如果尝试修改逗号运算符的结果或在下一个序列点之后访问它,则行为未定义.
脚注97说:
逗号运算符不会产生左值.
这意味着您无法分配逗号运算符的结果.
重要的是要注意逗号运算符具有最低优先级,因此有些情况下使用()
可以产生很大的不同,例如:
#includeint main() { int x, y ; x = 1, 2 ; y = (3,4) ; printf( "%d %d\n", x, y ) ; }
将有以下输出:
1 4
逗号运算符将其两侧的两个表达式合并为一个,按从左到右的顺序对它们进行评估.右侧的值作为整个表达式的值返回.
(expr1, expr2)
就像{ expr1; expr2; }
你可以expr2
在函数调用或赋值中使用结果.
在for
循环中经常可以看到初始化或维护多个变量,如下所示:
for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh) { /* do something with low and high and put new values in newlow and newhigh */ }
除此之外,我只是在另一种情况下"愤怒地"使用它,当包装两个应该总是在宏中一起运行的操作时.我们有代码将各种二进制值复制到字节缓冲区中以便在网络上发送,并且指针保持在我们已经达到的位置:
unsigned char outbuff[BUFFSIZE]; unsigned char *ptr = outbuff; *ptr++ = first_byte_value; *ptr++ = second_byte_value; send_buff(outbuff, (int)(ptr - outbuff));
在值为short
s或int
s的情况下,我们这样做:
*((short *)ptr)++ = short_value; *((int *)ptr)++ = int_value;
后来我们读到这不是真正有效的C,因为(short *)ptr
它不再是l值而且不能递增,尽管我们的编译器当时并不介意.为了解决这个问题,我们将表达式分为两部分:
*(short *)ptr = short_value; ptr += sizeof(short);
但是,这种方法依赖于所有开发人员都记得将这两个语句放在一起.我们想要一个函数,你可以传入输出指针,值和值的类型.这是C,而不是带有模板的C++,我们不能使用任意类型的函数,所以我们选择了一个宏:
#define ASSIGN_INCR(p, val, type) ((*((type) *)(p) = (val)), (p) += sizeof(type))
通过使用逗号运算符,我们可以在表达式中使用它或者作为我们希望的语句:
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));
我不是说这些例子都是好风格!实际上,我似乎记得Steve McConnell的Code Complete建议不要在for
循环中使用逗号运算符:为了可读性和可维护性,循环应该只由一个变量控制,并且for
行本身中的表达式应该只包含循环控制代码,没有其他额外的初始化或循环维护.
它导致多个语句的评估,但仅使用最后一个作为结果值(我认为是rvalue).
所以...
int f() { return 7; } int g() { return 8; } int x = (printf("assigning x"), f(), g() );
应该导致x设置为8.