Left-shifting (<<) un comportamento intero indefinito negativo in C ++ 11?

Lo spostamento a sinistra è negativo int Comportamento indefinito in C ++ 11?

I passaggi standard pertinenti qui sono 5.8:

2 / Il valore di E1 << E2 è E1 posizioni bit E2 spostate a sinistra; i bit vuoti sono riempiti a zero. Se E1 ha un tipo senza segno, il valore del risultato è E1 × 2E2, modulo ridotto uno più del valore massimo rappresentabile nel tipo di risultato. Altrimenti, se E1 ha un tipo firmato e un valore non negativo e E1 × 2E2 è rappresentabile nel tipo di risultato, allora questo è il valore risultante; in caso contrario, il comportamento non è definito.

La parte che mi confonde è:

Altrimenti, se E1 ha un tipo firmato e un valore non negativo e E1 × 2E2 è rappresentabile nel tipo di risultato, allora questo è il valore risultante; in caso contrario, il comportamento non è definito.

Questo dovrebbe essere interpretato nel senso che lo spostamento a sinistra di qualsiasi numero negativo è UB? O significa solo se LS è negativo e il risultato non si adatta al tipo di risultato, quindi è UB?

Inoltre, la clausola precedente dice:

1 / Gli operatori di spostamento <> raggruppano da sinistra a destra. shift-expression: additivo-espressione shift-expression <> additivo-espressione

Gli operandi devono essere di tipo di enumerazione integrale o senza ambito e vengono eseguite promozioni integrali.

Il tipo del risultato è quello dell’operando sinistro promosso. Il comportamento non è definito se l’operando destro è negativo o maggiore o uguale alla lunghezza in bit dell’operando sinistro promosso.

Ciò rende esplicito che l’utilizzo di un numero negativo per uno degli operandi è UB. Se fosse UB a usare un negativo per l’altro operando, mi aspetto che venga chiarito anche qui.

Quindi, linea di fondo, è:

 -1 << 1 

Comportamento indefinito?


@Angew ha fornito un’interpretazione psudocodice dello standardese che esprime sinteticamente una ansible (probabile) interpretazione valida. Altri si sono chiesti se questa domanda riguardasse davvero l’applicabilità del linguaggio “il comportamento non è definito” rispetto al nostro uso (StackOverflow) della frase “comportamento indefinito”. Questa modifica è per fornire ulteriori chiarimenti su ciò che sto cercando di chiedere.

@ L’interpretazione di Angew dello Standardese è:

 if (typeof(E1) == unsigned integral) value = E1 * 2^E2 % blah blah; else if (typeof(E1) == signed integral && E1 >= 0 && representable(E1 * 2^E2)) value = E1 * 2^E2; else value = undefined; 

Ciò a cui questa domanda si riduce in realtà è questa: in realtà è l’interpretazione corretta:

 value = E1 left-shift-by (E2) switch (typeof(E1)) { case unsigned integral : value = E1 * 2^E2 % blah blah; break; case signed integral : if (E1 >= 0) { if (representable(E1 * 2^E2)) { value = E1 * 2^E2; } else { value = undefined; } } break; } 

?

Sidenote, osservando questo in termini di psudocode, mi rende abbastanza chiaro che l’interpretazione di @ Agnew è corretta.

Sì, direi che è indefinito. Se traduciamo lo standardese in pseudo-codice:

 if (typeof(E1) == unsigned integral) value = E1 * 2^E2 % blah blah; else if (typeof(E1) == signed integral && E1 >= 0 && representable(E1 * 2^E2)) value = E1 * 2^E2; else value = undefined; 

Direi che il motivo per cui sono espliciti riguardo l’operando sulla mano destra e non su quello sulla mano sinistra è che la paragrpah che citi (quella con il caso dell’operando di destra) si applica a entrambi i turni di sinistra e di destra.

Per l’operando di sinistra, la regola è diversa. Lo spostamento verso sinistra di un negativo non è definito, lo spostamento verso destra è definito dall’implementazione.

Questo dovrebbe essere interpretato nel senso che lo spostamento a sinistra di qualsiasi numero negativo è UB?

Sì, il comportamento non è definito quando viene assegnato un numero negativo. Il comportamento viene definito solo quando sono vere entrambe le seguenti condizioni:

  • il numero è non negativo
  • E1 × 2 E2 è rappresentabile nel tipo di risultato

Questo è letteralmente ciò che “se E1 ha un tipo firmato e un valore non negativo e E1 × 2 E2 è rappresentabile nel tipo di risultato, allora questo è il valore risultante, altrimenti il ​​comportamento non è definito” sta dicendo:

 if X and Y then Z else U 

Risposta come da Domanda:

La domanda è davvero:

Possiamo equiparare il termine “il comportamento non è definito” equivale esattamente al termine “comportamento indefinito”.

Come è attualmente scritto significa “comportamento indefinito”.

Commento personale sulla situazione

Ma non sono convinto che sia l’intenzione degli autori.
Se è l’intenzione degli autori, probabilmente dovremmo avere una nota che spieghi perché. Ma io sono più incline a credere che l’autore significhi che il risultato di tale operazione è indefinito perché la rappresentazione dei numeri negativi non è esplicitamente definita dallo standard. Se la rappresentazione di numeri negativi non è definita in modo esplicito per i negativi, spostare i bit in giro porterebbe a un valore indefinito.

In entrambi i casi, la formulazione (o spiegazione) deve essere stretta / estesa per renderla meno ambigua.