当前位置:  开发笔记 > 编程语言 > 正文

逗号运算符是做什么的?

如何解决《逗号运算符是做什么的?》经验,为你挑选了5个好方法。

什么是,经营者用C呢?



1> lillq..:

表达方式:

(expression1,  expression2)

首先计算expression1,然后计算expression2,并为整个表达式返回expression2的值.


@James:逗号操作的值始终是最后一个表达式的值.在任何时候,"i"都没有值5,4,3,2或1.它只是0.除非表达式有副作用,否则几乎没用.
请注意,有逗号表达的LHS的评价和RHS的评价(见[沙菲克Yaghmour](http://stackoverflow.com/users/1708801/shafik-yaghmour)的[之间的全序列中的点回答](http://stackoverflow.com/a/18444099/15168)来自C99标准的报价).这是逗号运算符的重要属性.
“ i = b,c;”等效于“(i = b),c`”,因为赋值“ =”的优先级高于逗号运算符“,”。逗号运算符的优先级最低。
然后如果我写i =(5,4,3,2,1,0)然后理想情况下应该返回0,对吗?但我被赋予了5的价值?你能帮我理解我哪里错了吗?

2> crashmstr..:

我见过最常用的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);
}


嘿,太漂亮了!我经常不得不在一个循环中做非正统的事情来解决这个问题.
@staticsan不要害怕在身体中使用`while(1)`和`break;`语句.试图强制将代码的突破部分强制进入while测试或者进入do-while测试,这通常是浪费精力并使代码更难理解.
@jamesdlin ......人们还在读它.如果你有话要说,那就说吧.论坛有复活线程的问题,因为线程通常按上一篇文章的日期排序.StackOverflow没有这样的问题.
虽然你做了类似的事情,但它可能不那么模糊,更具可读性:`while(read_string(s)&& s.len()> 5)`.显然,如果`read_string`没有返回值(或者没有有意义的返回值),那将无效.(编辑:对不起,没看到这篇文章有多久了.)
@potrzebie我喜欢逗号方法比`while(1)`和`break`更好;
是的,对于很少使用的操作员来说,这是出色的DRY *和理由。(*第二个例子非常令人反感!)

3> Shafik Yaghm..:

该逗号操作将评估左操作数,丢弃的结果,然后计算右边的操作数,这将是这个结果.链接中提到的惯用法是在初始化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说:

逗号运算符不会产生左值.

这意味着您无法分配逗号运算符的结果.

重要的是要注意逗号运算符具有最低优先级,因此有些情况下使用()可以产生很大的不同,例如:

#include 

int main()
{
    int x, y ;

    x = 1, 2 ;
    y = (3,4) ;

    printf( "%d %d\n", x, y ) ;
}

将有以下输出:

1 4



4> Paul Stephen..:

逗号运算符将其两侧的两个表达式合并为一个,按从左到右的顺序对它们进行评估.右侧的值作为整个表达式的值返回. (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));

在值为shorts或ints的情况下,我们这样做:

*((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行本身中的表达式应该只包含循环控制代码,没有其他额外的初始化或循环维护.



5> Ben Collins..:

它导致多个语句的评估,但仅使用最后一个作为结果值(我认为是rvalue).

所以...

int f() { return 7; }
int g() { return 8; }

int x = (printf("assigning x"), f(), g() );

应该导致x设置为8.

推荐阅读
放ch养奶牛
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有