Como exatamente o operador?: Trabalha em C?

10

Eu tenho uma pergunta, como o compilador opera no seguinte código:

#include<stdio.h>

int main(void)
{
  int b=12, c=11;
  int d = (b == c++) ? (c+1) : (c-1);
  printf("d = %i\n", d);
}

Eu não sou certo porque o resultado é d = 11.

J0S
fonte
11
Por que você não tem certeza? O que mais você esperaria e por quê?
Gerhardh 11/02
2
Não recordo a semântica precisa envolvida, mas você pode estar observando um comportamento indefinido.
chepner 11/02
3
Não, @chepner, existe um ponto de sequência após avaliar a condição de um ternário, antes de avaliar a alternativa selecionada. Isso evita o vetor UB, suponho que você esteja pensando.
John Bollinger
Sim, não tenho certeza de onde pensei que o compilador teria uma escolha.
chepner 11/02

Respostas:

6

Em int d = (b == c++) ? (c+1) : (c-1);:

  • O valor de c++é o valor atual de c11. Separadamente, cé incrementado para 12.
  • b == 11é falso, pois bé 12.
  • Como (b == c++)é falso, (c-1)é usado. Além disso, o incremento de caté 12 deve ser concluído neste ponto.
  • Dado que cé 12, c-1é 11.
  • d é inicializado com esse valor, 11.
Eric Postpischil
fonte
5

De acordo com o padrão C (operador condicional 6.5.15)

4 O primeiro operando é avaliado; existe um ponto de sequência entre sua avaliação e a avaliação do segundo ou terceiro operando (o que for avaliado). O segundo operando é avaliado apenas se o primeiro comparar com 0; o terceiro operando é avaliado apenas se o primeiro for comparado a 0; o resultado é o valor do segundo ou terceiro operando (o que for avaliado), convertido para o tipo descrito abaixo.110)

Então, na expressão inicial desta declaração

int d = (b == c++) ? (c+1) : (c-1);

a variável bé comparada com o valor da variável cporque o operador pós-incremento retorna o valor do seu operando antes de incrementá-lo.

Como os valores não são iguais entre si ( bé definido como 12 enquanto cé definido como 11), a subexpressão (c-1)é avaliada.

De acordo com a citação, existe um ponto de sequência após a avaliação da condição do operador. Isso significa que após a avaliação da condição ctem o valor 12após a aplicação do operador pós-incremento à variável c. Como resultado, a variável d é inicializada pelo valor 1( 12 - 1).

Vlad de Moscou
fonte
2
A única resposta correta - este caso específico deve ser respondido mencionando o ponto de sequência em ?:. Como normalmente em C, combinar ++com outras operações no mesmo operando é um comportamento indefinido. E esse código só funciona previsivelmente porque ?:possui várias regras especiais de floco de neve.
Lundin
4

Porque a condição é falsa, portanto, o falsecaso acontecerá :, c-1mas desde que você incrementou ca condição em c++, portanto, cé agora 12. O resultado é 12-1, que é 11.

EDIT: O que OP entendeu mal foi o pós-incremento.

Então, o que realmente acontece é assim:

#include<stdio.h>
int main(void)
{
  int b=12, c=11;
  int d;

  if (b == c) { // 12 == 11 ? -> false
    c = c + 1;
    d = c + 1;
  } else { // this executes since condition is false
    c = c + 1; // post increment -> c++ -> c = 12 now
    d = c - 1; // 12 - 1 = 11 -> d = 11
  }
  printf("d = %i\n", d);
}
Eraklon
fonte
11
Eu acho que o OP está se referindo à ordem das operações, considerando c++a condição. A condição é falsa, mas o valor original de cé usado para calcular c - 1, não a versão incrementada.
chepner 11/02
11
Eu pensei que sincero 12 == 11 + 1 é verdade ...
J0S 11/02
Mas isso não é verdade, já que o novo valor c é usado ou estou perdendo o ponto de vista?
Eraklon 11/02
Eu acho que pode haver um mal-entendido entre c++e++c
ChatterOne
@ N00b c++é o operador pós- incremento. O valor de c++é 11, com o efeito colateral de fazer c == 12. ++cteria o valor de 12.
chepner 11/02
4

Traduzido para uma declaração if regular, seu código ficaria assim:

int b=12, c=11;
int d;

if (b == c++)
   d = c+1;
else
   d = c-1;

A pista aqui é que c é incrementado após a condição ser verificada. Então você entra no elseestado, mas c já tem o valor 12 lá.

Ulisses
fonte
1

Consulte Operador ternário.

Sintaxe

doença ? value_if_true: value_if_false

Então você escreveu

int d = (b == c++) ? (c+1) : (c-1);

Nessa situação, o resultado será 11 porque, após as verificações, o valor 'c' é aumentado (c + 1 = 12) e somente depois disso define o valor 'd' como c (12) -1, que é 11.

Se você usou, por exemplo:

int d = (b == ++c) ? (c+1) : (c-1);

O valor "c" seria aumentado antes de verificar a instrução, portanto seria verdadeiro e o valor "d" seria c (12) +1, que é 13.

Neto Costa
fonte