Domanda

#include<stdio.h>
int main(void)
{
  char c = 0x80;
  printf("%d\n", c << 1);
  return 0;
}

L'uscita è -256 in questo caso.Se scrivo c << 0 quindi l'output è -128.

Non capisco la logica dietro questo codice.

È stato utile?

Soluzione

Già il punto di partenza è problematica:

char c = 0x80;

Se (come apparentemente nel tuo caso) char è un tipo firmato, si sta assegnando il numero intero costante 128 a un tipo che è garantito solo per i valori contenere fino a 127. Il tuo compilatore quindi può scegliere di dare un certo valore implementazione definito (-128 nel tuo caso credo) o di emettere un errore di campo.

Poi si sta facendo uno spostamento a sinistra su quel valore negativo. Questo dà comportamento non definito. In totale si hanno diverse scelte implementative definito più un comportamento indefinito che determinano il risultato:

  • signedness di char
  • la scelta di come convertire 128 a signed char
  • la larghezza del char
  • la rappresentazione segno di int (ci sono tre possibilità)
  • la scelta su come implementare (o meno) di spostamento a sinistra su int negativo

Può essere un buon esercizio per voi a guardare in su tutti questi casi un per vedere quali possono essere i diversi risultati.

In sintesi alcune raccomandazioni:

  • scegliere una costante appropriata per inizializzare una variabile
  • non fare aritmetica con char pianura
  • non fare spostamento a sinistra sui tipi firmati

Altri suggerimenti

char potrebbero essere firmati sulla tua piattaforma, nel qual caso 0x80 rappresenta -128 (assumendo il complemento a due).

Quando un char viene utilizzato come operando con il << operatore, viene promosso a int (ancora -128).Quindi quando applichi lo spostamento a sinistra, ottieni -256.Tecnicamente, lo spostamento dei valori negativi lo è definito dall'implementazione indefinito, ma quello che vedi è un comportamento tipico.

c viene assegnato 0x80. Supponendo byte di 8 bit, il valore in rappresentazione binaria, è 10000000. A quanto pare, sulla vostra piattaforma, char è un tipo firmato. Così, 0x80 (vale a dire 10000000) corrisponde a -128.

Quando << viene applicato ad un valore char, è promosso al int e il segno è conservato. Così, quando spostato una volta a sinistra, con interi a 32 bit, diventa 11111111111111111111111100000000 (complemento a due) che è -256.

Solo una side-nota. Da una prospettiva fondo chiuso, spostamento bit per bit (e mascheramento) si basa sulla parola di lunghezza di un'architettura (espressa in bit). La lunghezza di una parola, varia dall'architettura all'architettura.

Vedere questa pagina Wiki per lunghezze di parola dall'architettura

Se si conosce la lunghezza di parola dell'architettura bersaglio, si può utilizzare il bit-shifting per moltiplicare e dividere (in alcuni casi), più veloce rispetto all'utilizzo operandi.

Vedere questa pagina Wiki per i diagrammi interessanti di bit-shifting

Poiché codice bit-shifted è architettura dipendente, può non impegna una parte specifica del codice bit spostata funziona allo stesso modo dall'architettura all'architettura. Tuttavia, una volta che si ha familiarità con l'idea di differenti lunghezze di parola per diverse architetture, po-shifting diventa meno misterioso e più prevedibile.

Per fortuna, oggi abbiamo 8, 16, 32, e 64 lunghezze di parola bit, ed esclusivamente a 8 lunghezze di caratteri bit. Nei tempi dell'antica computing, un'architettura potrebbe avere un 12, o 15, o di una lunghezza di parola a 23 bit (ecc, fino alla nausea).

Mi chiedo perché il compilatore non si lamentano con un avvertimento che 0x80 non si adatta a char, che sulla vostra piattaforma può rappresentare solo valori da -0x80 a 0x7F.

Prova questo pezzo di codice:

 #include <stdio.h>
 #include <limits.h>
 #include <stdlib.h>

 int main() {
      printf("char can represent values from %d to %d.\n", CHAR_MIN, CHAR_MAX);
      return EXIT_SUCCESS;
 }

La vostra situazione è chiamata TROPPO PIENO.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top