[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home] [volume] [parte]


Capitolo 592.   C: «stdint.h»

Il file stdint.h della libreria standard definisce principalmente dei tipi interi, alternativi a quelli tradizionali, riferiti in modo più diretto al rango. Assieme a questi tipi interi definisce anche delle macro-variabili che consentono di conoscere i limiti esatti di tali tipi, oltre ad altre macro-variabili con i limiti di tipi interi speciali, dichiarati in altri file.

Lo standard prescrive che alcuni dei tipi definiti nel file stdint.h siano opzionali, purché sia rispettato un certo ordine (per esempio, se viene definito un tipo intero con segno, deve essere prevista anche una versione di quel tipo senza segno e viceversa). A tale proposito, le macro-variabili con le quali si possono verificare i limiti, servono anche per consentire al programmatore di verificare la disponibilità o meno del tipo relativo, attraverso istruzioni del precompilatore del tipo #ifdef.

L'esempio proposto si riferisce a un elaboratore x86-32 ed è abbastanza conforme alla configurazione che si può trovare in un sistema GNU/Linux.

592.1   Tipi interi ad ampiezza esatta

Lo standard prescrive un gruppo facoltativo di tipi interi il cui rango è definito precisamente dal nome. Si tratta dei tipi intn_t (con segno) e uintn_t (senza segno), dove n esprime la quantità di bit che compone l'intero. Si tratta necessariamente di tipi facoltativi, perché non è possibile stabilire in modo sicuro che in ogni architettura siano gestibili tipi interi di una data quantità di bit; per esempio, in una certa achitettura «X» potrebbero essere gestiti tipi interi a 8, 16 e 32 bit, mentre in un'architettura «Y» i tipi disponibili effettivamente potrebbero essere a 8, 16, 24 e 32 bit.

typedef signed char             int8_t;
typedef short int               int16_t;
typedef int                     int32_t;        // x86-32
typedef long long int           int64_t;        // x86-32

typedef unsigned char           uint8_t;
typedef unsigned short int      uint16_t;
typedef unsigned int            uint32_t;       // x86-32
typedef unsigned long long int  uint64_t;       // x86-32

Le macro-variabili usate per definire i limiti di questi valori interi hanno nomi del tipo INTn_MIN, INTn_MAX e UINTn_MAX, per indicare rispettivamente: il valore minimo dei tipi con segno; il valore massimo dei tipi con segno; il valore massimo dei tipi senza segno. Lo standard prescrive precisamente questi valori minimi e massimi, dando per scontato che i valori negativi si rappresentino con il complemento a due:

Macro-variabile Valore standard
INTn_MIN
-(2n-1)
INTn_MAX
2n-1-1
UINTn_MAX
2n-1
#define INT8_MIN                (-0x80)
#define INT16_MIN               (-0x8000)
#define INT32_MIN               (-0x80000000)
#define INT64_MIN               (-0x8000000000000000LL)

#define INT8_MAX                  0x7F
#define INT16_MAX                 0x7FFF
#define INT32_MAX                 0x7FFFFFFF
#define INT64_MAX                 0x7FFFFFFFFFFFFFFFLL

#define UINT8_MAX                 0xFF
#define UINT16_MAX                0xFFFF
#define UINT32_MAX                0xFFFFFFFFU
#define UINT64_MAX                0xFFFFFFFFFFFFFFFFULL

592.2   Tipi interi di rango minimo

Un gruppo richiesto espressamente dallo standard riguarda tipi interi il cui rango sia tale da garantire la rappresentazione di almeno n bit, utilizzando comunque la quantità minima possibile di bit. In questo caso i nomi sono int_leastn_t per i tipi con segno e uint_leastn_t per quelli senza segno. Lo standard prescrive che siano previsti necessariamente i tipi a 8, 16, 32 e 64 bit, mentre ammette che ne siano disponibili anche altri.

typedef signed char             int_least8_t;
typedef short int               int_least16_t;
typedef int                     int_least32_t;  // x86-32
typedef long long int           int_least64_t;  // x86-32

typedef unsigned char           uint_least8_t;
typedef unsigned short int      uint_least16_t;
typedef unsigned int            uint_least32_t; // x86-32
typedef unsigned long long int  uint_least64_t; // x86-32

Le macro-variabili usate per definire i limiti di questi valori interi hanno nomi del tipo INT_LEASTn_MIN, INT_LEASTn_MAX e UINT_LEASTn_MAX, per indicare rispettivamente: il valore minimo dei tipi con segno; il valore massimo dei tipi con segno; il valore massimo dei tipi senza segno. Lo standard attribuisce questi limiti in modo indipendente dalla rappresentazione dei valori negativi, ma tali limiti possono essere estesi in senso assoluto:

Macro-variabile Valore standard che può essere superato in termini assoluti
INT_LEASTn_MIN
-(2n-1-1)
INT_LEASTn_MAX
2n-1-1
UINT_LEASTn_MAX
2n-1
#define INT_LEAST8_MIN          (-0x80)
#define INT_LEAST16_MIN         (-0x8000)
#define INT_LEAST32_MIN         (-0x80000000)
#define INT_LEAST64_MIN         (-0x8000000000000000LL)

#define INT_LEAST8_MAX            0x7F
#define INT_LEAST16_MAX           0x7FFF
#define INT_LEAST32_MAX           0x7FFFFFFF
#define INT_LEAST64_MAX           0x7FFFFFFFFFFFFFFFLL

#define UINT_LEAST8_MAX           0xFF
#define UINT_LEAST16_MAX          0xFFFF
#define UINT_LEAST32_MAX          0xFFFFFFFFU
#define UINT_LEAST64_MAX          0xFFFFFFFFFFFFFFFFULL

Ai tipi interi di rango minimo sono associate anche delle macro-istruzioni, il cui scopo è quello di consentire la rappresentazione corretta dei valori costanti:

INTn_C(valore)
UINTn_C(valore)

In pratica, per indicare il valore costante 1 234 567 890, precisando che va inteso come un tipo uint_least64_t, si deve scrivere: UINT64_C(1234567890). Il valore costante in sé, può essere espresso in qualunque modo, purché sia ammissibile nel contesto comune.

#define INT8_C(VAL)     VAL
#define INT16_C(VAL)    VAL
#define INT32_C(VAL)    VAL             // x86-32
#define INT64_C(VAL)    VAL ## LL       // x86-32

#define UINT8_C(VAL)    VAL
#define UINT16_C(VAL)   VAL
#define UINT32_C(VAL)   VAL ## U        // x86-32
#define UINT64_C(VAL)   VAL ## ULL      // x86-32

È evidente che, nel caso dell'esempio mostrato, UINT64_C(1234567890) corrisponde a 1234567890ULL.

592.3   Tipi interi «veloci»

Un altro gruppo di tipi richiesti dallo standard è quello il cui rango è tale da consentire la rappresentazione di almeno n bit, utilizzando la quantità minima di bit che garantisce tempi ottimali di elaborazione. In questo caso i nomi sono int_fastn_t per i tipi con segno e uint_fastn_t per quelli senza segno. Lo standard prescrive che siano previsti necessariamente i tipi a 8, 16, 32 e 64 bit, mentre ammette che ne siano disponibili anche altri.

typedef signed char             int_fast8_t;
typedef int                     int_fast16_t;   // x86-32
typedef int                     int_fast32_t;   // x86-32
typedef long long int           int_fast64_t;   // x86-32

typedef unsigned char           uint_fast8_t;
typedef unsigned int            uint_fast16_t;  // x86-32
typedef unsigned int            uint_fast32_t;  // x86-32
typedef unsigned long long int  uint_fast64_t;  // x86-32

Come suggerisce l'esempio, è ragionevole pensare che, dove possibile, il rango usato effettivamente sia quello del tipo intero normale.

Le macro-variabili usate per definire i limiti di questi valori interi hanno nomi del tipo INT_FASTn_MIN, INT_FASTn_MAX e UINT_FASTn_MAX, per indicare rispettivamente: il valore minimo dei tipi con segno; il valore massimo dei tipi con segno; il valore massimo dei tipi senza segno. Lo standard attribuisce questi limiti in modo indipendente dalla rappresentazione dei valori negativi, ma tali limiti possono essere estesi in senso assoluto:

Macro-variabile Valore standard che può essere superato in termini assoluti
INT_FASTn_MIN
-(2n-1-1)
INT_FASTn_MAX
2n-1-1
UINT_FASTn_MAX
2n-1
#define INT_FAST8_MIN          (-0x80)
#define INT_FAST16_MIN         (-0x80000000)
#define INT_FAST32_MIN         (-0x80000000)
#define INT_FAST64_MIN         (-0x8000000000000000LL)

#define INT_FAST8_MAX            0x7F
#define INT_FAST16_MAX           0x7FFFFFFF
#define INT_FAST32_MAX           0x7FFFFFFF
#define INT_FAST64_MAX           0x7FFFFFFFFFFFFFFFLL

#define UINT_FAST8_MAX           0xFF
#define UINT_FAST16_MAX          0xFFFFFFFFU
#define UINT_FAST32_MAX          0xFFFFFFFFU
#define UINT_FAST64_MAX          0xFFFFFFFFFFFFFFFFULL

592.4   Tipi interi per rappresentare dei puntatori

Sono previsti due tipi opzionali interi, adatti a contenere il valore di un puntatore, garantendo che la conversione da e verso void * avvenga sempre correttamente. Per la precisione si tratta di intptr_t e uintptr_t, dove il primo è un intero con segno, mentre il secondo è senza segno.

typedef int                     intptr_t;       // x86-32
typedef unsigned int            uintptr_t;      // x86-32

Le macro-variabili usate per definire i limiti di questi valori interi sono INTPTR_MIN, INTPTR_MAX e UINTPTR_MAX, per indicare rispettivamente: il valore minimo con segno, il valore massimo con segno e il valore massimo senza segno. Lo standard attribuisce dei limiti riferiti ad architetture in grado di indirizzare al massimo con 16 bit e ovviamente vanno adattati alla realtà dell'architettura effettiva:

Macro-variabile Valore standard che può essere superato in termini assoluti
INTPTR_MIN
-(215-1)
INTPTR_MAX
215-1
UINTPTR_MAX
216-1
#define INTPTR_MIN              (-0x80000000)
#define INTPTR_MAX                0x7FFFFFFF
#define UINTPTR_MAX               0xFFFFFFFFU

592.5   Tipi interi di rango massimo

Per poter rappresentare in modo indipendente dall'architettura degli interi di rango massimo, sono previsti due tipi specifici, richiesti espressamente dallo standard: intmax_t e uintmax_t. Le macro-variabili che definiscono i limiti sono: INTMAX_MIN, INTMAX_MAX e UINTMAX_MAX. Lo standard prescrive che si tratti di variabili con un rango di almeno 64 bit.

typedef long long int           intmax_t;       // x86-32
typedef unsigned long long int  uintmax_t;      // x86-32
Macro-variabile Valore standard che può essere superato in termini assoluti
INTMAX_MIN
-(263-1)
INTMAX_MAX
263-1
UINTMAX_MAX
264-1

Anche ai tipi interi di rango massimo sono associate delle macro-istruzioni per facilitare la rappresentazione corretta dei valori costanti:

INTMAX_C(valore)
UINTMAX_C(valore)

In pratica, per indicare il valore costante 1 234 567 890, precisando che va inteso come un tipo uintmax_t, si deve scrivere: UINTMAX_C(1234567890). Il valore costante in sé, può essere espresso in qualunque modo, purché sia ammissibile nel contesto comune.

#define INTMAX_C(VAL)   VAL ## LL       // x86-32
#define UINTMAX_C(VAL)  VAL ## ULL      // x86-32

A questo punto, anche la definizione dei valori minimi e massimi diventa più agevole:

#define INTMAX_MIN      (-INTMAX_C(0x8000000000000000))     // x86-32
#define INTMAX_MAX       (INTMAX_C(0x7FFFFFFFFFFFFFFF))     // x86-32
#define UINTMAX_MAX     (UINTMAX_C(0xFFFFFFFFFFFFFFFF))    // x86-32

592.6   Limiti per altri tipi interi

Altri tipi interi dichiarati al di fuori del file stdint.h hanno i limiti definiti qui. Ne viene mostrata solo una tabella riepilogativa.

Macro-variabile Descrizione
PTRDIFF_MIN
PTRDIFF_MAX
Rappresentano il valore minimo e il valore massimo rappresentabile in una variabile ptrdiff t.
SIG_ATOMIC_MIN
SIG_ATOMIC_MAX
Rappresentano il valore minimo e il valore massimo rappresentabile in una variabile sig_atomic_t.
SIZE_MAX
Rappresenta il valore massimo rappresentabile in una variabile size_t, la quale è destinata a contenere valori senza segno.
WCHAR_MIN
WCHAR_MAX
Rappresentano il valore minimo e il valore massimo rappresentabile in una variabile wchar_t.
WINT_MIN
WINT_MAX
Rappresentano il valore minimo e il valore massimo rappresentabile in una variabile wint_t.

L'esempio seguente riporta i valori usati in un sistema GNU/Linux con architettura x86-32, a parte il caso di wchar_t e wint_t che si intendono rispettivamente a 32 bit senza segno e 64 bit con segno:

#define PTRDIFF_MIN             (-0x80000000)   // x86-32
#define PTRDIFF_MAX               0x7FFFFFFF    // x86-32

#define SIG_ATOMIC_MIN          (-0x80000000)   // x86-32
#define SIG_ATOMIC_MAX            0x7FFFFFFF    // x86-32

#define SIZE_MAX                  0xFFFFFFFFU   // x86-32

#define WCHAR_MIN                 0x00000000
#define WCHAR_MAX                 0xFFFFFFFFU   // x86-32

#define WINT_MIN        (-0x8000000000000000LL) // x86-32
#define WINT_MAX          0x7FFFFFFFFFFFFFFFLL  // x86-32

592.7   Riferimenti


Appunti di informatica libera 2008 --- Copyright © 2000-2008 Daniele Giacomini -- <appunti2 (ad) gmail·com>


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome c_171_stdint_h_187.htm

[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home]

Valid ISO-HTML!

CSS validator!

Gjlg Metamotore e Web Directory