O que exatamente é a regra “como se”?

89

Como diz o título,

O que exatamente é a regra "como se"?

Uma resposta típica que se obteria é:

A regra que permite toda e qualquer transformação de código que não altere o comportamento observável do programa

De vez em quando, continuamos obtendo comportamentos de certas implementações que são atribuídas a esta regra. Muitas vezes erroneamente. Então, o que exatamente é essa regra. A norma não menciona claramente esta regra como uma seção ou parágrafo, então o que exatamente se enquadra no escopo desta regra? Para mim, parece uma área cinzenta que não é definida em detalhes pelo padrão. Alguém pode explicar os detalhes citando as referências da norma?

Observação: marcar isso como C e C ++, porque é relevante para ambas as linguagens.

Alok Save
fonte
2
Refere-se à máquina abstrata.
Alexey Frunze
" Marcando isso como C e C ++, porque é relevante para ambas as linguagens " É relevante em qualquer linguagem.
curioso
@AlexeyFrunze " Refere-se à máquina abstrata " Refere-se ao estado da "máquina abstrata" sendo uma ferramenta e não um fim, e sendo irrelevante em termos de conformidade, porque é "abstrato" que é uma ferramenta de especificação não real.
curioso

Respostas:

98

O que é " como se regra "?

A regra " como se " basicamente define quais transformações uma implementação pode realizar em um programa C ++ válido. Resumindo, todas as transformações que não afetam o " comportamento observável " de um programa (veja abaixo uma definição precisa) são permitidas.

O objetivo é dar liberdade às implementações para realizar otimizações, desde que o comportamento do programa permaneça compatível com a semântica especificada pelo padrão C ++ em termos de uma máquina abstrata.


Onde o Padrão introduz esta regra?

O C ++ 11 Standard introduz a regra " como se " no Parágrafo 1.9 / 1:

As descrições semânticas neste Padrão Internacional definem uma máquina abstrata não determinística parametrizada. Este Padrão Internacional não impõe requisitos à estrutura de implementações em conformidade. Em particular, eles não precisam copiar ou emular a estrutura da máquina abstrata. Em vez disso, as implementações em conformidade são necessárias para emular (apenas) o comportamento observável da máquina abstrata, conforme explicado abaixo.

Além disso, uma nota de rodapé explicativa adiciona:

Esta disposição é às vezes chamada de regra "como se" , porque uma implementação é livre para desconsiderar qualquer requisito desta Norma, desde que o resultado seja como se o requisito tivesse sido obedecido, tanto quanto pode ser determinado a partir do comportamento observável do programa. Por exemplo, uma implementação real não precisa avaliar parte de uma expressão se puder deduzir que seu valor não é usado e que nenhum efeito colateral que afeta o comportamento observável do programa é produzido.


O que a regra exige exatamente?

O parágrafo 1.9 / 5 especifica ainda:

Uma implementação conforme executando um programa bem formado deve produzir o mesmo comportamento observável que uma das possíveis execuções da instância correspondente da máquina abstrata com o mesmo programa e a mesma entrada . No entanto, se qualquer uma dessas execuções contiver uma operação indefinida, esta Norma Internacional não impõe nenhum requisito à implementação que executa esse programa com aquela entrada (nem mesmo com relação às operações anteriores à primeira operação indefinida).

É importante enfatizar que esta restrição se aplica apenas ao "executar um programa bem formado" e que os resultados possíveis da execução de um programa que contém comportamento indefinido são irrestritos. Isso é explicitado no Parágrafo 1.9 / 4 também:

Certas outras operações são descritas nesta Norma como indefinidas (por exemplo, o efeito de tentar modificar um objeto const). [Nota: Este Padrão Internacional não impõe requisitos sobre o comportamento de programas que contêm comportamento indefinido . —Enviar nota]

Finalmente, com relação à definição de " comportamento observável ", o parágrafo 1.9 / 8 é o seguinte:

Os requisitos mínimos em uma implementação em conformidade são:

- O acesso a objetos voláteis é avaliado estritamente de acordo com as regras da máquina abstrata.

- No encerramento do programa, todos os dados gravados em arquivos devem ser idênticos a um dos resultados possíveis que a execução do programa de acordo com a semântica abstrata teria produzido.

- A dinâmica de entrada e saída de dispositivos interativos deve ocorrer de tal forma que a saída do prompt seja realmente entregue antes que um programa aguarde a entrada. O que constitui um dispositivo interativo é definido pela implementação.

Esses são coletivamente chamados de comportamento observável do programa . [ Nota : Correspondências mais rigorosas entre semântica abstrata e real podem ser definidas por cada implementação. - nota final ]


Existem situações em que esta regra não se aplica?

Até onde sei, a única exceção à regra " como se " é a eliminação de copiar / mover, que é permitida mesmo que o construtor de cópia, o construtor de movimento ou o destruidor de uma classe tenham efeitos colaterais. As condições exatas para isso são especificadas no Parágrafo 12.8 / 31:

Quando certos critérios são atendidos, uma implementação pode omitir a construção copiar / mover de um objeto de classe, mesmo se o construtor selecionado para a operação de copiar / mover e / ou o destruidor do objeto tiver efeitos colaterais . [...]

Andy Prowl
fonte
2
Eu vi esta citação. O que não está claro é a definição de comportamento observável. O que exatamente se qualifica como um comportamento observável? A elisão de cópia sendo uma exceção à regra de as-if é bastante conhecida e não faz parte da minha pergunta realmente.
Alok Save
2
@AlokSave: Bem, no padrão C, vemos "Acessar um objeto volátil, modificar um objeto, modificar um arquivo ou chamar uma função que faz qualquer uma dessas operações são todos efeitos colaterais". Presumivelmente, há algo equivalente no (s) padrão (ões) C ++. Informalmente, acho que "qualquer coisa que mude sua interação com o mundo exterior".
Oliver Charlesworth
1
Qualquer comportamento que altera o estado da máquina abstrata (ou seja, algo que altera uma variável passada ou uma variável global, ou lê e grava em dispositivos de E / S).
Mats Petersson
1
Isso significa que excluir um loop infinito que não faz nada é permitido, desde que nada observável aconteça depois?
Harold
5
Um ponto a ser observado em particular é que se aplica apenas a programas legais . Qualquer coisa que invoque um comportamento indefinido está explicitamente fora de qualquer cobertura.
vonbrand
15

Em C11, a regra nunca é chamada por esse nome. Porém, C, assim como C ++, define o comportamento em termos de máquina abstrata. A regra de as-if está em C11 5.1.2.3p4 e p6 :

  1. Na máquina abstrata, todas as expressões são avaliadas conforme especificado pela semântica. Uma implementação real não precisa avaliar parte de uma expressão se puder deduzir que seu valor não é usado e que nenhum efeito colateral necessário é produzido (incluindo aqueles causados ​​pela chamada de uma função ou acesso a um objeto volátil).

  2. [...]

  3. Os requisitos mínimos em uma implementação em conformidade são:

    • Os acessos aos volatileobjetos são avaliados estritamente de acordo com as regras da máquina abstrata.
    • No encerramento do programa, todos os dados gravados em arquivos devem ser idênticos ao resultado que a execução do programa de acordo com a semântica abstrata teria produzido.
    • A dinâmica de entrada e saída de dispositivos interativos deve ocorrer conforme especificado em 7.21.3 . A intenção desses requisitos é que a saída sem buffer ou com buffer de linha apareça o mais rápido possível, para garantir que as mensagens de aviso realmente apareçam antes de um programa aguardando entrada.

     

    Este é o comportamento observável do programa.

Antti Haapala
fonte
-1

Em C, C ++, Ada, Java, SML ... em qualquer linguagem de programação bem especificada, descrevendo o (s) comportamento (s) (geralmente muitos possíveis, não determinísticos) de um programa (exposto a uma série de interações em portas de E / S) , não há uma regra de como se distinta .

Um exemplo de regra distinta é aquela que diz que uma divisão por zero levanta uma exceção (Ada, Caml) ou uma desreferenciação nula levanta uma exceção (Java). Você poderia alterar a regra para especificar outra coisa e acabaria com uma linguagem diferente (que algumas pessoas preferem chamar de "dialeto" (*). Uma regra distinta existe para especificar alguns usos distintos de uma linguagem de programação como um a regra gramatical cobre algumas construções de sintaxe.

(*) Um dialeto de acordo com alguns lingüistas é uma língua com um "exército". nesse contexto, isso poderia significar uma linguagem de programação sem um comitê e uma indústria específica de editores de compiladores.

A regra de como se não é uma regra distinta ; não cobre nenhum programa em particular e nem mesmo é uma regra que possa ser discutida, removida ou alterada de alguma forma : a chamada "regra" simplesmente reitera que a semântica do programa está definida e só pode ser portável (universalmente) definido, em termos das interações visíveis de uma execução do programa com o mundo "externo".

O mundo externo pode ser interfaces de E / S (stdio), uma GUI ou até mesmo um interpretador interativo que produz o valor resultante de uma linguagem de aplicativo pura. Em C e C ++ inclui os acessos (vagamente especificados) a objetos voláteis, o que é outra maneira de dizer que alguns objetos em um determinado ponto devem ser representados na memória estritamente de acordo com a ABI (Interface Binária do Aplicativo), sem nunca mencionar a ABI explicitamente.

A definição do que é um traço de execução , também chamado de comportamento visível ou observável, define o que se entende por "regra como se". A regra como se tenta explicá-lo, mas ao fazer isso, ela confunde as pessoas mais do que esclarece as coisas, pois dá a expressão de ser uma regra semântica adicional, dando mais margem de manobra para a implementação.

Resumo:

  • A chamada "regra como se" não relaxa nenhuma restrição nas implementações.
  • Você não pode remover a regra as-if em qualquer linguagem de programação especificada em termos de comportamento visível (traços de execução compostos para interação com o mundo externo) para obter um dialeto distinto.
  • Você não pode adicionar a regra as-if a qualquer linguagem de programação não especificada em termos de comportamento visível.
cara curioso
fonte
Se as pessoas acreditam que estou errado e há uma "regra como se" distinta, por que não tentam descrever uma variante de C ++ (um dialeto) sem essa "regra"? O que a especificação C ++ significaria sem ela? Seria absolutamente impossível dizer se um compilador está em conformidade. Ou até mesmo para definir conformar.
curioso