Domanda Perché C ++ consente la conversione implicita da int a unsigned int?


Considera il seguente codice:

void foo(unsigned int x)
{

}

int main()
{
  foo(-5);
  return 0;
}

Compila senza problemi. Errori come questo possono causare molti problemi e sono difficili da trovare. Perché il C ++ consente tale conversione?


17
2018-03-10 17:16


origine


risposte:


La risposta breve è perché C supportava in origine tali conversioni e non voleva rompere il software esistente in C ++.

Si noti che alcuni compilatori avviseranno su questo. Per esempio g++ -Wconversion avvertirà su quel costrutto.

In molti casi è utile la conversione implicita, ad esempio quando int è stato utilizzato nei calcoli, ma il risultato finale non sarà mai negativo (noto dall'algoritmo e opzionalmente affermato).

EDIT: ulteriore spiegazione probabile: Ricorda che in origine C era un linguaggio molto più flessibile rispetto a C ++ è ora. Con le dichiarazioni delle funzioni in stile K & R non sarebbe stato possibile per il compilatore rilevare tali conversioni implicite, quindi perché preoccuparsi di limitarlo nella lingua. Ad esempio il tuo codice sembrerebbe più o meno come questo:

int foo(x)
unsigned int x
{

}

int main()
{
  foo(-5);
  return 0;
}

mentre la sola dichiarazione sarebbe stata int foo(x);

Il compilatore si affidava effettivamente al programmatore per passare i tipi giusti a ogni chiamata di funzione e non ha fatto conversioni al sito di chiamata. Quindi, quando la funzione è stata effettivamente chiamata, i dati nello stack (ecc.) Sono stati interpretati nel modo in cui è stata indicata la dichiarazione di funzione.

Una volta che il codice è stato scritto e basato su quel tipo di conversione implicita, sarebbe diventato molto più difficile rimuoverlo da ANSI C anche quando i prototipi di funzione sono stati aggiunti con informazioni di tipo reali. Questo è probabilmente il motivo per cui rimane in C anche adesso. Poi C ++ è arrivato e ha deciso di non rompere la compatibilità con C, continuando a consentire conversioni così implicite.


20
2018-03-10 17:20



  • Solo un'altra stranezza di un linguaggio che ha un sacco di stranezze stravaganti.
  • La conversione è ben definita per avvolgere, il che può essere utile in alcuni casi.
  • È retrocompatibile con C, che lo fa per le ragioni di cui sopra.

Fai la tua scelta.


6
2018-03-10 17:21



@ user168715 ha ragione. C ++ è stato inizialmente progettato per essere un superset di C, fingendo di essere il più retro compatibile possibile. La filosofia "C" è quella di consegnare la maggior parte delle responsabilità al programmatore, invece di escludere cose pericolose. Per i programmatori C è un paradiso, per i programmatori Java, è un inferno ... una questione di gusti.

Scaverò gli standard per vedere dove esattamente è scritto, ma non ho tempo per questo ora. Modificherò la mia risposta il prima possibile.

Sono anche d'accordo sul fatto che parte della libertà ereditata può portare a errori che sono davvero difficili da debugare, quindi aggiungo quello che è stato detto che in g ++ puoi attivare un avviso per impedirti di fare questo tipo di errore: -Wconversion bandiera.

-Wconversion

Avverti le conversioni implicite che possono alterare un valore. Ciò comprende   conversioni tra reale e intero,   come abs (x) quando x è doppio;   conversioni tra firmato e   unsigned, come unsigned ui = -1; e   conversioni a tipi più piccoli, come   sqrtf (M_PI). Non avvisare per esplicito   cala come abs ((int) x) e ui =   (senza segno) -1 o se il valore non lo è   cambiato dalla conversione come in abs   (2.0). Avvertenze sulle conversioni   tra interi firmati e non firmati   può essere disabilitato usando   -Wno-sign-conversione.

Per C ++, avvisare anche per confondere la risoluzione di sovraccarico per l'utente   conversioni; e conversioni che lo faranno   non utilizzare mai un operatore di conversione di tipo:   conversioni a vuoto, lo stesso tipo, a   classe base o un riferimento a loro.   Avvertenze sulle conversioni tra   gli interi firmati e non firmati sono   disabilitato di default in C ++ a meno che   -La conversione della parola è esplicitamente abilitata.

Altri compilatori potrebbero avere bandiere simili.


4
2018-03-10 17:31



Al momento dello standard C originale, la conversione era già consentita da molti (tutti?) Compilatori. Sulla base della motivazione, sembra che ci sia stata poca (eventuale) discussione sulla possibilità di consentire tali conversioni implicite. Quando C ++ è arrivato, tali conversioni implicite erano sufficientemente comuni che eliminarle avrebbe reso il linguaggio incompatibile con una grande quantità di codice C. Sarebbe probabilmente aver reso C ++ più pulito; sarebbe certamente l'hanno reso molto meno utilizzato - al punto che probabilmente non sarebbe mai andato oltre lo stadio "C with Classes", e anche quello sarebbe solo una nota a piè di pagina ignorata nella storia dei laboratori Bell.

L'unica vera questione lungo questa linea era tra le regole di "preservazione del valore" e "conservazione non firmata" quando si promuovevano valori non firmati "più piccoli" di int. La differenza tra i due si verifica quando (ad esempio) si aggiunge un corto senza segno a un carattere non firmato.

Le regole di conservazione senza segno affermano che si promuove sia a int unsigned. Le regole di conservazione del valore dicono che promuovi entrambi i valori int, Se può rappresentare tutti i valori del tipo originale (ad esempio, il caso comune di char a 8 bit, short a 16 bit e int a 32 bit). D'altra parte, se int e short sono entrambi a 16 bit, così int non può rappresentare tutti i valori di unsigned short, quindi promuovi l'unsigned short a unsigned int (nota che è ancora considerata una promozione, anche se accade solo quando è veramente non una promozione - cioè, i due tipi hanno le stesse dimensioni).

Nel bene o nel male, (ed è stato sostenuto in entrambe le direzioni molte volte) il comitato ha scelto di preservare il valore piuttosto che le promozioni di conservazione non firmate. Nota, tuttavia, che si tratta di una conversione nella direzione opposta: piuttosto che da firmata a non firmata, si tratta della conversione da non firmata a firma.


0
2018-03-10 18:54



Perché lo standard consente la conversione implicita da signed a unsigned tipi.

Anche (int)a + (unsigned)b risultati a unsigned - questo è uno standard c ++.


-1
2018-03-10 17:21