2013-09-04 8 views
14

Ancora una volta, sto insegnando un corso in cui posso rispondere alle domande degli studenti su C. Ecco uno non so la risposta a: C'era una logica dietro l'accettazione di signed come modificatore predefinito per C? Si sarebbe pensato che unsigned fosse la scelta naturale. Quindi, questa è stata davvero una decisione di progettazione?firmato come predefinito in C

+3

La "motivazione" in sé non è completamente corretta. Per semplice 'char', non è sempre' firmato'. –

+0

Perché l'unsigned int è più naturale? Penso che molti problemi del mondo reale si occupino sia di valori positivi che negativi. – jxh

+0

@jxh Più precisamente, la maggior parte dei problemi del mondo reale riguardano i numeri _small_, ovvero i numeri relativamente vicini a 0. Penso che la maggior parte delle persone nella maggior parte dei casi abbia molte più probabilità di aver bisogno di numeri sotto (o almeno vicini) 0 per richiedere numeri maggiori di (o anche vicini a) MAX_INT. I numeri firmati mantengono entrambi i limiti superiore e inferiore il più lontano possibile dai numeri più comunemente usati. –

risposta

15

In termini di standard di (dal momento che la tua domanda è etichettato come tale), signed è stato segnato come predefinito perché è così che è stato con le implementazioni di C che è venuto prima di lo standard.

I mandati standard ANSI/ISO originali dovevano codificare la pratica esistente piuttosto che creare una nuova lingua. Da qui il comportamento delle implementazioni pre-standard, è stato il fattore più importante, secondo il documento logica:

La Carta X3J11 originale chiaramente mandato codificazione comune prassi esistente, ed il Comitato C89 tenuto veloce per un precedente laddove questo era chiaro e inequivocabile.

La stragrande maggioranza del linguaggio definito da C89 era esattamente lo stesso definito nell'Appendice A della prima edizione di The C Programming Language di Brian Kernighan e Dennis Ritchie, e come è stato implementato in quasi tutti i traduttori C del tempo . (Questo documento è di seguito denominato K & R.)

Se stai cercando di scoprire perché le implementazioni pre-standard preferito signed, probabilmente dovrete esaminare l'architettura del PDP- n macchine per le quali UNIX e C sono stati originariamente sviluppati.

La pagina History of C mostra che unsigned era in realtà un ritardatario relativo alla lingua, che appare a volte nel metà degli anni '70:

Durante 1973-1980, la lingua è cresciuto un po ': la struttura tipo di guadagnato senza segno, tipi lunghi, di unione e di enumerazione, e le strutture divennero oggetti di prima classe (mancava solo una notazione per i letterali).

+0

Hah. Interessante. Mi sto appoggiando a questa risposta, ma mi rendo conto che in qualche modo la domanda pone una domanda: perché le precedenti implementazioni C hanno 'firmato' come predefinito? –

+2

@Dervin, perché no? Il tipo "firmato" è adatto sia ai valori positivi che negativi, utilizzati nella vita quotidiana. –

+0

@Eric, giusto, era solo che pensavo che i modificatori avvenissero nello stesso momento (cosa che ho sbagliato a pensare), così ero nella fase di progettazione della lingua, avrei reso il char non firmato, e avrei chiesto al programmatore di dimmi esplicitamente che voleva diversamente. La storia è così interesante! –

0

La firma predefinita di char non è definita dalla lingua. È definito dall'implementazione. Alcune CPU hanno un carattere più naturale, mentre altre sono più naturalmente non firmate.

+0

cosa intendi con "naturale" firmato? –

+0

@DervinThunk: la naturalezza delle istruzioni per espandere una quantità di 8 bit a 16 bit o più ha presupposti particolari, in particolare CPU prima del 1985 circa. Per promuovere un char in un int nella direzione * innaturale * sono necessarie ulteriori istruzioni per renderlo tale. La direzione * naturale * richiede solo una singola istruzione. – wallyk

+0

@wallyk, sei sicuro che lo standard non imponga la firma di plain 'int'? Ricordo che lo standard impone il più piccolo intervallo di valori che può essere ripreso da 'int'. Vedi http://stackoverflow.com/questions/6155784/range-of-values-in-c-int-and-long-32-64-bits –

3

Secondo The Development of the C Language, la nozione di unsigned era un'estensione del linguaggio quando caratteristiche venivano aggiunti ad esso tra il 1973 e il 1980. Anche se non esplicitamente dichiarato, il racconto suggerisce che non è stato introdotto fino al 1977 (vedi Portabilità, paragrafo 3).

Quindi, l'impostazione predefinita per firmare era dovuta al fatto che inizialmente la lingua aveva solo tipi firmati.

5

Si tratta in gran parte di compatibilità con le versioni precedenti e la discendenza di C da lingue precedenti che non supportava facilmente sia interi firmati che non firmati.

C deriva da un linguaggio più vecchio chiamato B, derivato da un linguaggio ancora più vecchio chiamato BCPL (che era una versione semplificata di CPL).

BCPL era in gran parte untyped lingua.Una dichiarazione di variabile non ha specificato il tipo di un oggetto; piuttosto, un'operazione su una data variabile la tratterà come se fosse di un certo tipo.

Gli operatori BCPL +, -, *, / e REM trattati loro operandi come firmato interi, e ha dato risultati interi.

Se BCPL supportava numeri interi senza segno, allora avrebbe dovuto avere un altro gruppo di operandi senza operatore, oppure non sarebbe stato in grado di rappresentare affatto numeri negativi. (Si noti che BCPL non supportava virgola mobile.)

La sintassi di B era molto diversa da quella di BCPL (e più vicina a C), ma conservava gran parte della stessa semantica. In particolare, le variabili e le funzioni erano di tipo intero per impostazione predefinita e non esisteva la parola chiave unsigned.

Early C, basato su B, inoltre non ha avuto una parola chiave unsigned. Aveva solo quattro tipi numerici fondamentali: char, int, float e double. (unsigned è stato aggiunto, insieme a long, union e enum, un po 'di tempo tra il 1973 e il 1980.) Data la natura debolmente tipizzata del linguaggio, i programmatori talvolta usavano i puntatori quando avevano bisogno di aritmetica non firmata.

La "funzione" che un'entità senza tipo dichiarato è implicitamente di tipo int è stata mantenuta in C finché lo standard ISO del 1999 non ha rimosso la regola "implicita int".

Inoltre, i tipi di interi con segno tendono ad essere più utili rispetto ai tipi senza segno. La capacità di rappresentare valori negativi può essere estremamente conveniente. Data la semantica wraparound tipica, un errore in una sottrazione senza firma di due valori piccoli può produrre un valore positivo enorme (3 - 4 == 65535 ad esempio, per un tipo senza segno a 16 bit). Anche nel dominio di programmazione dei sistemi che è l'obiettivo principale di tutti questi linguaggi, a volte è necessario rappresentare valori negativi (ad esempio un cambiamento in una certa quantità).

Riferimenti:

0

unsigned la semantica è garantita per essere più semplice: modulo base-2 n senza eccezioni. Ma non fare un'ipotesi su cosa sia n: la dimensione dell'intervallo non deve essere uguale a quella del tipo firmato corrispondente.

L'unico requisito è che tutti i valori con segno positivo possano essere rappresentati anche dal corrispondente tipo senza segno.

Un'implementazione valida di unsigned consiste nell'utilizzare l'aritmetica firmata con complemento a due e azzerare il bit di segno dopo ogni operazione.Questo non è probabile che si manifesti nella vita reale, ma le macchine con aritmetica non a due complementi possono avere più problemi nel cercare di aggirare la logica del numero negativo.

In pratica, i numeri negativi sono una caratteristica essenziale di qualsiasi piattaforma hardware, ma la possibilità di trattare un intero registro come un numero positivo è solo una ciliegina sulla torta. C è progettato per avvolgere maggiormente le parti più efficienti dell'hardware.