Perché tutti digitano i caratteri sui tipi C standard?


103

Se si desidera utilizzare Qt , devi abbracciare quint8, quint16e così via.

Se si desidera utilizzare GLib , è necessario il benvenuto guint8, guint16e così via.

Su Linux ci sono u32, s16e così via.

uC / OS definisce SINT32, UINT16e così via.

E se devi usare una combinazione di queste cose, è meglio che tu sia preparato per i guai. Perché sulla tua macchina u32sarà typedeffinito longe quint32sarà typedeffinito inte il compilatore si lamenterà .

Perché lo fanno tutti, se c'è <stdint.h>? È una specie di tradizione per le biblioteche?


8
@Mehrdad nella programmazione del microcontrollore puoi avere ogni sorta di cose. Su AVR Mega ad esempio (e di conseguenza sul famoso Arduino) l'int è a 16 bit. Potrebbe essere una brutta sorpresa. A mio parere, "corto non firmato" richiede uno sforzo di digitazione maggiore. E mi ha sempre reso triste usare "unsigned char" per <s> byte </s> ottetto. Personaggio non firmato, davvero?
Amomum

2
@ Mehrdad Il punto è che non puoi esserne davvero sicuro. Questo è esattamente il motivo per cui è stdint.hstato inventato.
glglgl

1
@glglgl: ecco un altro modo per esaminare il problema: non stai facendo esattamente la domanda sbagliata? Se stai prendendo di mira più sistemi, perché in primo luogo codificare arbitrariamente il numero di bit nel codice? cioè, perché non dire sizeof(int) * CHAR_BIT(per esempio) e usarlo? Se il tuo intè troppo piccolo per rappresentare il tuo intervallo (ad esempio un indice di array), allora quasi certamente non dovresti usarlo intcomunque, ma qualcosa di simile size_t. Perché avrebbe int32più senso? L'unica volta che la larghezza fissa ha senso è per la comunicazione tra i sistemi (ad es. Formato file / rete) ...
user541686

1
@ Mehrdad No. A volte ho valori (come da un ADC o altro) che devo memorizzare. So che sono larghe 16 bit. Quindi la cosa migliore da usare è uint16_t(o forse la sua fasto leastvariante). Il mio punto è: questi tipi sono convenienti da usare e hanno la loro ragione di esistenza.
glglgl

1
@Mehrdad: Suggerirei che, supponendo che valga la pena di produrre codice di qualità, dovresti definire i tuoi typedef funzionali che significano il modo di interagire con la mia API / il resto del mio codice , e definirli su basi tecniche in termini di Typedef "tecnici" come size_te / o uint64_t.
PJTraill

Risposte:


80

stdint.hnon esisteva quando queste biblioteche venivano sviluppate. Quindi ogni libreria ha creato i propri file typedef.


4
E va bene, suppongo che la mancanza di stdint.h sia una buona ragione, ma perché anche oggi questi typedef sono su int, long e così per e non su tipi stdint? Li renderebbe intercambiabili almeno
Amomum

25
@Amomum "Perché Glib (che è stato sviluppato su Linux) non ha usato i typedef di Linux?" Sebbene la "base di casa" di glib sia certamente Linux, è certamente una libreria portatile. La definizione dei propri tipi garantisce la portabilità: è sufficiente adattare una piccola intestazione che abbini i tipi di libreria ai rispettivi tipi di piattaforma di destinazione appropriati.
Peter - Ripristina Monica il

3
@Amomum Perché Glib (che è stato sviluppato su Linux) ... No, non lo era. Glib è stato creato molto prima del kernel Linux.
andy256

5
@ andy256 "GLib" non è l'abbreviazione di "glibc". È una libreria che si è ramificata da gtk. Non è più vecchio di Linux.

2
@ andy256: glib è il 1998, linux è il 1991. IOW, GLib è stato creato molto dopo Linux.
MSalters

40

Per le librerie più vecchie, questo è necessario perché l'intestazione in questione (stdint.h ) non esisteva.

C'è ancora, tuttavia, un problema in giro: quei tipi ( uint64_te altri) sono una funzionalità opzionale nello standard. Quindi un'implementazione conforme potrebbe non essere fornita con loro e quindi costringere le biblioteche a includerli ancora oggi.


14
I uintN_ttipi sono facoltativi, ma i tipi uint_leastN_te uint_fastN_tnon lo sono.
Kusalananda

7
@Kusalananda: Purtroppo quelli sono di utilità limitata.
Gare di leggerezza in orbita

16
Ovviamente il motivo per cui sono opzionali è che non è garantito che ci siano tipi interi con esattamente quel numero di bit. C supporta ancora architetture con dimensioni intere piuttosto dispari.
celtschk

5
@LightnessRacesinOrbit: come sono di utilità limitata? Devo ammettere che, a parte le interfacce hardware, non vedo perché avresti bisogno di un numero esatto di bit, piuttosto che solo un minimo, per assicurarti che tutti i tuoi valori si adattino.
celtschk

23
@Amomum I typedef sono richiesti se l'implementazione ha tipi che soddisfano i requisiti: "Tuttavia, se un'implementazione fornisce tipi interi con larghezze di 8, 16, 32 o 64 bit, nessun bit di riempimento e (per i tipi con segno) che hanno una rappresentazione in complemento a due, definirà i corrispondenti nomi typedef. " (citazione da N1570, 7.20.1.1 "Tipi interi a larghezza esatta") Quindi, se la libreria standard non li ha, una libreria di terze parti non potrebbe neanche farlo, a quanto pare.
Eric M Schmidt

13

stdint.h è stato standardizzato dal 1999. È più probabile che molte applicazioni definiscano (effettivamente alias) tipi per mantenere una parziale indipendenza dall'architettura della macchina sottostante.

Forniscono agli sviluppatori la certezza che i tipi utilizzati nella loro applicazione corrispondono ai presupposti specifici del progetto sul comportamento che potrebbe non corrispondere allo standard del linguaggio o all'implementazione del compilatore.

La pratica si rispecchia nella facciata orientata agli oggetti modello di progettazione ed è molto abusata dagli sviluppatori che invariabilmente scrivono classi wrapper per tutte le librerie importate.

Quando i compilatori erano molto meno standard e le architetture delle macchine potevano variare da mainframe di parole di 16 bit, 18 bit e 36 bit, questa era una considerazione molto più importante. La pratica è molto meno rilevante ora in un mondo che converge su sistemi embedded ARM a 32 bit. Rimane una preoccupazione per i microcontrollori di fascia bassa con mappe di memoria dispari .


1
Certo, stdint.hè stato standardizzato dal 1999, ma da quanto tempo è disponibile in pratica? Le persone trascinano i piedi implementando e adottando nuovi standard e durante quel lungo periodo di transizione, i vecchi metodi sono ancora un must.
Siyuan Ren

1
Un brutto trucco stdint.hè che anche su piattaforme in cui ad es. longE int32_thanno le stesse dimensioni e rappresentazione, non è necessario che lanciare un int32_t*a long*produrrà un puntatore che può accedere in modo affidabile a un file int32_t. Non posso credere che gli autori dello Standard pensassero ovvio che i tipi compatibili con il layout dovessero essere compatibili con gli alias, ma poiché non si sono preoccupati di dirlo, gli autori di gcc e IIRC clang pensano che il linguaggio sarebbe migliorato ignorando anche l'aliasing nei casi in cui è ovvio.
supercat

2
@supercat - probabilmente vale la pena sottoporlo come errore al comitato C ... perché è gratuitamente stupido , per
usare un

@LThode: Affinché il comitato C riconosca che come errore sarebbe necessario dichiarare ufficialmente il comportamento di clang e gcc come ottuso. Pensi che succederà? Il meglio che si potrebbe sperare (e IMHO il modo logico di procedere) sarebbe definire modi per i programmi per specificare "modalità di aliasing". Se un programma specifica che può accettare regole di aliasing molto rigide, un compilatore potrebbe usarlo per consentire ottimizzazioni oltre ciò che è attualmente possibile. Se un programma specifica che richiede regole un po 'più
facili da

... ma consentirebbe comunque molte utili ottimizzazioni, quindi un compilatore potrebbe generare codice molto più efficiente di quanto sarebbe possibile -fno-strict-alias, ma che funzionerebbe comunque. Anche se non ci fosse una base di codice esistente, nessun singolo insieme di regole potrebbe raggiungere l'equilibrio ottimale tra ottimizzazione e semantica per tutte le applicazioni, perché applicazioni diverse hanno esigenze diverse. Aggiungi la base di codice esistente e la necessità di modalità diverse dovrebbe essere chiara.
supercat

3

Quindi hai il potere di typedef char in int.

Un "orrore del codice" ha detto che un'intestazione di una società aveva un punto in cui un programmatore voleva un valore booleano e un carattere era il tipo logico nativo per il lavoro, e così scriveva typedef bool char . Poi in seguito qualcuno ha trovato un numero intero come la scelta più logica e ha scritto typedef bool int. Il risultato, secoli prima di Unicode, era virtualmente typedef char int.

Un bel po 'di lungimiranza, compatibilità futura, credo.

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.