Cos'è esattamente la regola del "come se"?


90

Come dice il titolo,

Cos'è esattamente la regola "come se"?

Una tipica risposta che si potrebbe ottenere è:

La regola che consente tutte le trasformazioni del codice che non modificano il comportamento osservabile del programma

Di tanto in tanto continuiamo a ricevere comportamenti da determinate implementazioni attribuite a questa regola. Molte volte a torto. Allora, qual è esattamente questa regola. Lo standard non menziona chiaramente questa regola come sezione o paragrafo, quindi cosa rientra esattamente nell'ambito di competenza di questa regola? A me sembra una zona grigia non definita in dettaglio dallo standard. Qualcuno può approfondire i dettagli citando i riferimenti dallo standard?

Nota: contrassegnare questo come C e C ++ entrambi, perché è rilevante per entrambi i linguaggi.


2
Si riferisce alla macchina astratta.
Alexey Frunze

" Contrassegnare questo come C e C ++ entrambi, perché è rilevante per entrambi i linguaggi " È rilevante in qualsiasi lingua.
curioso

@AlexeyFrunze " Si riferisce alla macchina astratta " Si riferisce allo stato della "macchina astratta" essendo uno strumento e non un fine, ed essendo irrilevante in termini di conformità, perché è "astratto" cioè uno strumento di specifica non reale.
curioso

Risposte:


100

Qual è la regola " come se "?

La regola " come se " definisce fondamentalmente quali trasformazioni un'implementazione è autorizzata a eseguire su un programma C ++ legale. In breve, sono consentite tutte le trasformazioni che non influenzano il " comportamento osservabile " di un programma (vedi sotto per una definizione precisa).

L'obiettivo è dare alle implementazioni la libertà di eseguire ottimizzazioni fintanto che il comportamento del programma rimane conforme alla semantica specificata dallo standard C ++ in termini di macchina astratta.


Dove lo Standard introduce questa regola?

Lo Standard C ++ 11 introduce la regola " come se " nel Paragrafo 1.9 / 1:

Le descrizioni semantiche in questo standard internazionale definiscono una macchina astratta non deterministica parametrizzata. La presente norma internazionale non pone alcun requisito sulla struttura delle implementazioni conformi. In particolare, non hanno bisogno di copiare o emulare la struttura della macchina astratta. Piuttosto, sono necessarie implementazioni conformi per emulare (solo) il comportamento osservabile della macchina astratta come spiegato di seguito.

Inoltre, una nota esplicativa aggiunge:

Questa disposizione è talvolta chiamata regola del "come se" , perché un'implementazione è libera di ignorare qualsiasi requisito della presente norma internazionale fintanto che il risultato è come se il requisito fosse stato rispettato, per quanto è possibile determinare dal comportamento osservabile del programma. Ad esempio, un'implementazione effettiva non ha bisogno di valutare parte di un'espressione se può dedurre che il suo valore non viene utilizzato e che non vengono prodotti effetti collaterali che influenzano il comportamento osservabile del programma.


Cosa impone esattamente la regola?

Il paragrafo 1.9 / 5 specifica inoltre:

Un'implementazione conforme che esegue un programma ben formato produrrà lo stesso comportamento osservabile di una delle possibili esecuzioni dell'istanza corrispondente della macchina astratta con lo stesso programma e lo stesso input . Tuttavia, se una di tali esecuzioni contiene un'operazione indefinita, la presente norma internazionale non impone alcun requisito all'implementazione che esegue quel programma con quell'input (nemmeno per quanto riguarda le operazioni che precedono la prima operazione non definita).

Vale la pena sottolineare che questo vincolo si applica solo quando "si esegue un programma ben formato" e che i possibili risultati dell'esecuzione di un programma che contiene un comportamento indefinito non sono vincolati. Ciò è reso esplicito anche nel Paragrafo 1.9 / 4:

Alcune altre operazioni sono descritte in questo standard internazionale come non definite (ad esempio, l'effetto del tentativo di modificare un oggetto const). [Nota: questo standard internazionale non impone requisiti sul comportamento dei programmi che contengono un comportamento indefinito . —End nota]

Infine, per quanto riguarda la definizione di " comportamento osservabile ", il paragrafo 1.9 / 8 è il seguente:

I requisiti minimi per un'implementazione conforme sono:

- Gli accessi agli oggetti volatili sono valutati rigorosamente secondo le regole della macchina astratta.

- Al termine del programma, tutti i dati scritti nei file devono essere identici ad uno dei possibili risultati che avrebbe prodotto l'esecuzione del programma secondo la semantica astratta.

- Le dinamiche di input e output dei dispositivi interattivi devono avvenire in modo tale che la richiesta di output sia effettivamente fornita prima che un programma attenda l'input. Ciò che costituisce un dispositivo interattivo è definito dall'implementazione.

Questi sono collettivamente indicati come il comportamento osservabile del programma . [ Nota : corrispondenze più stringenti tra semantica astratta ed effettiva possono essere definite da ciascuna implementazione. - nota finale ]


Ci sono situazioni in cui questa regola non si applica?

Per quanto ne so, l'unica eccezione alla regola " come se " è l'elisione copia / sposta, che è consentita anche se il costruttore di copia, il costruttore di mosse o il distruttore di una classe hanno effetti collaterali. Le condizioni esatte per questo sono specificate nel Paragrafo 12.8 / 31:

Quando vengono soddisfatti determinati criteri, un'implementazione può omettere la costruzione copia / sposta di un oggetto classe, anche se il costruttore selezionato per l'operazione copia / sposta e / o il distruttore per l'oggetto hanno effetti collaterali . [...]


2
Ho visto questa citazione. Ciò che non è chiaro è la definizione di comportamento osservabile. Cosa si qualifica esattamente come comportamento osservabile? Il fatto che l'elisione sia un'eccezione alla regola come se è abbastanza ben nota e non fa parte della mia domanda in realtà.
Alok Save

2
@AlokSave: Bene, nello standard C, vediamo "L'accesso a un oggetto volatile, la modifica di un oggetto, la modifica di un file o la chiamata a una funzione che esegue una di queste operazioni sono tutti effetti collaterali". Presumibilmente c'è qualcosa di equivalente negli standard C ++. In modo informale, immagino "tutto ciò che cambia la sua interazione con il mondo esterno".
Oliver Charlesworth

1
Qualsiasi comportamento che cambia lo stato della macchina astratta (quindi, qualcosa che cambia una variabile passata o una variabile globale, o legge e scrive su dispositivi I / O).
Mats Petersson

1
Ciò significa che l'eliminazione di un ciclo infinito che non fa nulla è consentita, purché non accada nulla di osservabile in seguito?
Harold

5
Un punto da notare in particolare è che si applica solo ai programmi legali . Tutto ciò che richiama un comportamento indefinito è esplicitamente fuori da ogni copertura.
vonbrand

15

In C11 la regola non viene mai chiamata con quel nome. Tuttavia C, proprio come C ++, definisce il comportamento in termini di macchina astratta. La regola as-if è in C11 5.1.2.3p4 e p6 :

  1. Nella macchina astratta, tutte le espressioni vengono valutate come specificato dalla semantica. Un'attuale implementazione non ha bisogno di valutare parte di un'espressione se può dedurre che il suo valore non viene utilizzato e che non vengono prodotti effetti collaterali necessari (inclusi quelli causati dalla chiamata a una funzione o dall'accesso a un oggetto volatile).

  2. [...]

  3. I requisiti minimi per un'implementazione conforme sono:

    • Gli accessi agli volatileoggetti vengono valutati rigorosamente secondo le regole della macchina astratta.
    • Al termine del programma, tutti i dati scritti nei file devono essere identici al risultato che avrebbe prodotto l'esecuzione del programma secondo la semantica astratta.
    • Le dinamiche di input e output dei dispositivi interattivi devono avvenire come specificato in 7.21.3 . Lo scopo di questi requisiti è che l'output senza buffer o con buffer di riga appaia il prima possibile, per garantire che i messaggi di prompt appaiano effettivamente prima che un programma sia in attesa di input.

     

    Questo è il comportamento osservabile del programma.


-1

In C, C ++, Ada, Java, SML ... in qualsiasi linguaggio di programmazione ben specificato descrivendo il comportamento (di solito molti possibili, non deterministici) di un programma (esposto a serie di interazioni sulle porte I / O) , non esiste una regola as-if distinta .

Un esempio di regola distinta è quella che dice che una divisione per zero solleva un'eccezione (Ada, Caml) o una dereferenziazione nulla solleva un'eccezione (Java). Potresti cambiare la regola per specificare qualcos'altro e ti ritroverai con un linguaggio diverso (che alcune persone preferirebbero chiamare un "dialetto" (*). Una regola distinta è lì per specificare alcuni usi distinti di un linguaggio di programmazione come un le regole grammaticali coprono alcuni costrutti di sintassi.

(*) Un dialetto secondo alcuni linguisti è una lingua con un "esercito". in quel contesto, ciò potrebbe significare un linguaggio di programmazione senza un comitato e un'industria specifica di editor di compilatori.

La regola come se non è una regola distinta ; non copre alcun programma in particolare e non è nemmeno una regola che potrebbe essere discussa, rimossa o alterata in alcun modo : la cosiddetta "regola" ribadisce semplicemente che la semantica del programma è definita e può essere solo portabile (universalmente) definito, in termini di interazioni visibili di un'esecuzione del programma con il mondo "esterno".

Il mondo esterno può essere interfacce I / O (stdio), una GUI, persino un interprete interattivo che emette il valore risultante di un linguaggio applicativo puro. In C e C ++ sono inclusi gli accessi (vagamente specificati) agli oggetti volatili, che è un altro modo per dire che alcuni oggetti in un dato punto devono essere rappresentati in memoria rigorosamente secondo l'ABI (Application Binary Interface) senza mai menzionare esplicitamente l'ABI.

La definizione di ciò che è una traccia di esecuzione , chiamato anche comportamento visibile o osservabile, definisce cosa si intende per "regola come se". La regola as-if cerca di spiegarlo, ma così facendo confonde le persone più di quanto chiarisca le cose in quanto dà l'espressione di essere una regola semantica aggiuntiva che dà più margine all'implementazione.

Sommario:

  • La cosiddetta "regola come se" non allenta alcun vincolo sulle implementazioni.
  • Non è possibile rimuovere la regola come se in alcun linguaggio di programmazione specificato in termini di comportamento visibile (tracce di esecuzione composte per l'interazione con il mondo esterno) per ottenere un dialetto distinto.
  • Non è possibile aggiungere la regola as-if a nessun linguaggio di programmazione non specificato in termini di comportamento visibile.

Se le persone credono che io abbia torto, e c'è una distinta "regola come se", perché non cercano di descrivere una variante del C ++ (un dialetto) senza quella "regola"? Cosa significherebbe la specifica C ++ anche senza? Sarebbe assolutamente impossibile dire se un compilatore è conforme. O anche per definire conforme.
Curiousguy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.