Pergunta

Como funciona o operador vírgula em C++?

Por exemplo, se eu fizer:

a = b, c;  

A acaba sendo igual a b ou c?

(Sim, eu sei que isso é fácil de testar - basta documentar aqui para que alguém encontre a resposta rapidamente.)

Atualizar: Esta questão expôs uma nuance ao usar o operador vírgula.Apenas para documentar isso:

a = b, c;    // a is set to the value of b!

a = (b, c);  // a is set to the value of c!

Na verdade, esta pergunta foi inspirada por um erro de digitação no código.O que pretendia ser

a = b;
c = d;

Se tornou

a = b,    //  <-  Note comma typo!
c = d;
Foi útil?

Solução

Seria igual a b.

O operador vírgula tem uma precedência menor que a atribuição.

Outras dicas

Tome cuidado para observar que o operador vírgula pode estar sobrecarregado em C++.O comportamento real pode, portanto, ser muito diferente do esperado.

Como um exemplo, Impulsionar.Espírito usa o operador vírgula de maneira bastante inteligente para implementar inicializadores de lista para tabelas de símbolos.Assim, torna a seguinte sintaxe possível e significativa:

keywords = "and", "or", "not", "xor";

Observe que devido à precedência do operador, o código é (intencionalmente!) idêntico ao

(((keywords = "and"), "or"), "not"), "xor";

Ou seja, o primeiro operador chamado é keywords.operator =("and") que retorna um objeto proxy no qual o restante operator,s são invocados:

keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");

O operador vírgula tem o mais baixo precedência de todos os operadores C/C++.Portanto, é sempre o último a ser vinculado a uma expressão, ou seja:

a = b, c;

é equivalente a:

(a = b), c;

Outro fato interessante é que o operador vírgula introduz um ponto de sequência.Isso significa que a expressão:

a+b, c(), d

é garantido que terá suas três subexpressões (a+b, c() e d) avaliados em ordem.Isto é significativo se eles tiverem efeitos colaterais.Normalmente, os compiladores podem avaliar subexpressões na ordem que acharem adequada;por exemplo, em uma chamada de função:

someFunc(arg1, arg2, arg3)

os argumentos podem ser avaliados em uma ordem arbitrária.Observe que as vírgulas na chamada de função são não operadores;eles são separadores.

O operador vírgula:

  • tem a menor precedência
  • é associativo à esquerda

Uma versão padrão do operador vírgula é definida para todos os tipos (integrados e personalizados) e funciona da seguinte maneira - fornecido exprA , exprB:

  • exprA é avaliado
  • o resultado de exprA é ignorado
  • exprB é avaliado
  • o resultado de exprB é retornado como o resultado de toda a expressão

Com a maioria dos operadores, o compilador pode escolher a ordem de execução e é até obrigado a pular a execução se isso não afetar o resultado final (por exemplo, false && foo() vai pular a chamada para foo).No entanto, este não é o caso do operador vírgula e as etapas acima sempre acontecerão*.

Na prática, o operador vírgula padrão funciona quase da mesma maneira que um ponto e vírgula.A diferença é que duas expressões separadas por ponto e vírgula formam duas instruções separadas, enquanto a separação por vírgula mantém tudo como uma única expressão.É por isso que o operador vírgula às vezes é usado nos seguintes cenários:

  • A sintaxe C requer um único expressão, não uma declaração.por exemplo.em if( HERE )
  • A sintaxe C requer uma única instrução, não mais, por ex.na inicialização do for laço for ( HERE ; ; )
  • Quando você quiser pular chaves e manter uma única instrução: if (foo) HERE ; (por favor, não faça isso, é muito feio!)

Quando uma instrução não é uma expressão, o ponto e vírgula não pode ser substituído por vírgula.Por exemplo, estes não são permitidos:

  • (foo, if (foo) bar) (if não é uma expressão)
  • int x, int y (declaração de variável não é uma expressão)

No seu caso temos:

  • a=b, c;, equivalente a a=b; c;, assumindo que a é do tipo que não sobrecarrega o operador vírgula.
  • a = b, c = d; equivalente a a=b; c=d;, assumindo que a é do tipo que não sobrecarrega o operador vírgula.

Observe que nem toda vírgula é na verdade um operador de vírgula.Algumas vírgulas que têm um significado completamente diferente:

  • int a, b; --- a lista de declarações de variáveis ​​é separada por vírgula, mas não são operadores de vírgula
  • int a=5, b=3; --- esta também é uma lista de declaração de variáveis ​​​​separada por vírgula
  • foo(x,y) --- lista de argumentos separados por vírgula.Na verdade, x e y pode ser avaliado em qualquer ordem!
  • FOO(x,y) --- lista de argumentos de macro separados por vírgula
  • foo<a,b> --- lista de argumentos de modelo separados por vírgula
  • int foo(int a, int b) --- lista de parâmetros separados por vírgula
  • Foo::Foo() : a(5), b(3) {} --- lista de inicializadores separados por vírgula em um construtor de classe

* Isso não é totalmente verdade se você aplicar otimizações.Se o compilador reconhecer que determinado trecho de código não tem absolutamente nenhum impacto sobre o restante, ele removerá as instruções desnecessárias.

Leitura adicional: http://en.wikipedia.org/wiki/Comma_operator

O valor de a vai ser b, mas o valor de a expressão vai ser c.Que está em

d = (a = b, c);

a seria igual a b, e d seria igual a c.

O valor de b será atribuído a a.Nada vai acontecer com c

O valor de a será igual a b, pois o operador vírgula tem precedência menor que o operador de atribuição.

Sim, o operador Vírgula tem precedência baixa que o operador Atribuição

#include<stdio.h>
int main()
{
          int i;
          i = (1,2,3);
          printf("i:%d\n",i);
          return 0;
}

Saída :eu=3
Porque o operador vírgula sempre retorna o valor mais à direita.
No caso de operador vírgula com Operador de Atribuição:

 int main()
{
      int i;
      i = 1,2,3;
      printf("i:%d\n",i);
      return 0;
}

Saída:eu=1
Como sabemos, o operador vírgula tem precedência menor que a atribuição.....

Primeiras coisas primeiro: Na verdade, a vírgula não é um operador, para o compilador é apenas um token que ganha um significado no contexto com outros tokens.

O que isso significa e por que se preocupar?

Exemplo 1:

Para entender a diferença entre o significado do mesmo token em um contexto diferente, damos uma olhada neste exemplo:

class Example {
   Foo<int, char*> ContentA;
}

Normalmente, um iniciante em C++ pensaria que esta expressão poderia/iria comparar coisas, mas é absolutamente errada, o significado do <, > e , os tokens dependem do contexto de uso.

A interpretação correta do exemplo acima é, obviamente, que se trata de uma instauração de um modelo.

Exemplo 2:

Quando escrevemos um loop for típico com mais de uma variável de inicialização e/ou mais de uma expressão que deve ser feita após cada iteração do loop, usamos vírgula também:

for(a=5,b=0;a<42;a++,b--)
   ...

O significado da vírgula depende do contexto de uso, aqui é o contexto da for construção.

O que realmente significa uma vírgula no contexto?

Para complicar ainda mais (como sempre em C++), o próprio operador vírgula pode estar sobrecarregado (graças a Konrad Rodolfo por apontar isso).

Voltando à questão, o Código

a = b, c;

significa para o compilador algo como

(a = b), c;

porque o prioridade do = token/operador é maior que a prioridade do , símbolo.

e isso é interpretado no contexto como

a = b;
c;

(observe que a interpretação depende do contexto, aqui não é uma chamada de função/método ou uma instanciação de modelo.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top