2010-01-13 17 views

risposta

78

Avrai voglia di utilizzare limits.h che fornisce le seguenti costanti (come per il riferimento collegato):

CHAR_BIT = number of bits in a char 
SCHAR_MIN = minimum value for a signed char 
SCHAR_MAX = maximum value for a signed char 
UCHAR_MAX = maximum value for an unsigned char 
CHAR_MIN = minimum value for a char 
CHAR_MAX = maximum value for a char 
MB_LEN_MAX = maximum multibyte length of a character accross locales 
SHRT_MIN = minimum value for a short 
SHRT_MAX = maximum value for a short 
USHRT_MAX = maximum value for an unsigned short 
INT_MIN = minimum value for an int 
INT_MAX = maximum value for an int 
UINT_MAX = maximum value for an unsigned int 
LONG_MIN = minimum value for a long 
LONG_MAX = maximum value for a long 
ULONG_MAX = maximum value for an unsigned long 
LLONG_MIN = minimum value for a long long 
LLONG_MAX = maximum value for a long long 
ULLONG_MAX = maximum value for an unsigned long long 

Dove U*_MIN è omesso per ovvie ragioni (di qualsiasi tipo senza segno ha un valore minimo di 0).

Allo stesso modo float.h prevede limiti per float e double tipi:

-FLT_MAX = most negative value of a float 
FLT_MAX = max value of a float 
-DBL_MAX = most negative value of a double 
DBL_MAX = max value of a double 
-LDBL_MAX = most negative value of a long double 
LDBL_MAX = max value of a long double 

Si dovrebbe leggere l'articolo su floats.h con attenzione, anche se float e double può contenere i valori minimo prescritto e, ma la precisione con cui ogni tipo può rappresentare i dati potrebbero non corrispondere a ciò che stai cercando di memorizzare. In particolare, è difficile memorizzare numeri eccezionalmente grandi con frazioni estremamente piccole collegate. Quindi, float.h fornisce un numero di altre costanti che aiutano a determinare se un float o un double possono, in realtà, rappresentare un numero particolare.

+1

qual è il valore minimo e massimo di un galleggiante? – SuperString

+0

FLT_MAX e FLT_MIN –

+2

'SIZE_MAX' (la dimensione massima di un' size_t') è un'altra utile. – caf

3

Il file di intestazione limits.h definisce le macro che si espandono in vari limiti e parametri dei tipi di interi standard.

+0

qual è il valore minimo del carattere unsigned char? – SuperString

+4

@Superstring, il valore minimo di qualsiasi tipo * senza segno * è 0. –

+4

Voglio valori negativi senza segno! :-) –

3

Guarda queste pagine su limits.h e float.h, che sono incluse come parte della libreria c standard.

23

"Ma glifo", ti sento chiedere, "cosa succede se devo determinare il valore massimo per un tipo opaco il cui massimo potrebbe eventualmente cambiare?" Potresti continuare: "E se si tratta di un typedef in una libreria che non controllo?"

Sono contento che l'abbiate chiesto, perché ho appena passato un paio d'ore a preparare una soluzione (che poi ho dovuto buttare via, perché non risolveva il mio problema reale).

È possibile utilizzare questa pratica macro maxof per determinare la dimensione di qualsiasi tipo di intero valido.

#define issigned(t) (((t)(-1)) < ((t) 0)) 

#define umaxof(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | \ 
        (0xFULL << ((sizeof(t) * 8ULL) - 4ULL))) 

#define smaxof(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | \ 
        (0x7ULL << ((sizeof(t) * 8ULL) - 4ULL))) 

#define maxof(t) ((unsigned long long) (issigned(t) ? smaxof(t) : umaxof(t))) 

Si può usare in questo modo:

int main(int argc, char** argv) { 
    printf("schar: %llx uchar: %llx\n", maxof(char), maxof(unsigned char)); 
    printf("sshort: %llx ushort: %llx\n", maxof(short), maxof(unsigned short)); 
    printf("sint: %llx uint: %llx\n", maxof(int), maxof(unsigned int)); 
    printf("slong: %llx ulong: %llx\n", maxof(long), maxof(unsigned long)); 
    printf("slong long: %llx ulong long: %llx\n", 
      maxof(long long), maxof(unsigned long long)); 
    return 0; 
} 

Se vuoi, puoi lanciare un '(t)' sul fronte a quelle macro in modo da dare un risultato della scrivi quello che stai chiedendo, e non devi fare casting per evitare avvisi.

+0

Non '' ((t) 0) 'funziona per max di unsigned? (non è così, ma non sono sicuro del perché ancora). – Gauthier

+0

Beh, funziona, ma richiede il typecast che hai menzionato. – Gauthier

+0

[Come rilevare se il tipo è firmato] (http://stackoverflow.com/a/7470062/991816) – DanSkeel

3

ho scritto alcune macro che restituiscono il min e max di qualsiasi tipo, a prescindere dal signedness:

#define MAX_OF(type) \ 
    (((type)(~0LLU) > (type)((1LLU<<((sizeof(type)<<3)-1))-1LLU)) ? (long long unsigned int)(type)(~0LLU) : (long long unsigned int)(type)((1LLU<<((sizeof(type)<<3)-1))-1LLU)) 
#define MIN_OF(type) \ 
    (((type)(1LLU<<((sizeof(type)<<3)-1)) < (type)1) ? (long long int)((~0LLU)-((1LLU<<((sizeof(type)<<3)-1))-1LLU)) : 0LL) 

codice Esempio:

#include <stdio.h> 
#include <sys/types.h> 
#include <inttypes.h> 

#define MAX_OF(type) \ 
    (((type)(~0LLU) > (type)((1LLU<<((sizeof(type)<<3)-1))-1LLU)) ? (long long unsigned int)(type)(~0LLU) : (long long unsigned int)(type)((1LLU<<((sizeof(type)<<3)-1))-1LLU)) 
#define MIN_OF(type) \ 
    (((type)(1LLU<<((sizeof(type)<<3)-1)) < (type)1) ? (long long int)((~0LLU)-((1LLU<<((sizeof(type)<<3)-1))-1LLU)) : 0LL) 

int main(void) 
{ 
    printf("uint32_t = %lld..%llu\n", MIN_OF(uint32_t), MAX_OF(uint32_t)); 
    printf("int32_t = %lld..%llu\n", MIN_OF(int32_t), MAX_OF(int32_t)); 
    printf("uint64_t = %lld..%llu\n", MIN_OF(uint64_t), MAX_OF(uint64_t)); 
    printf("int64_t = %lld..%llu\n", MIN_OF(int64_t), MAX_OF(int64_t)); 
    printf("size_t = %lld..%llu\n", MIN_OF(size_t), MAX_OF(size_t)); 
    printf("ssize_t = %lld..%llu\n", MIN_OF(ssize_t), MAX_OF(ssize_t)); 
    printf("pid_t = %lld..%llu\n", MIN_OF(pid_t), MAX_OF(pid_t)); 
    printf("time_t = %lld..%llu\n", MIN_OF(time_t), MAX_OF(time_t)); 
    printf("intptr_t = %lld..%llu\n", MIN_OF(intptr_t), MAX_OF(intptr_t)); 
    printf("unsigned char = %lld..%llu\n", MIN_OF(unsigned char), MAX_OF(unsigned char)); 
    printf("char = %lld..%llu\n", MIN_OF(char), MAX_OF(char)); 
    printf("uint8_t = %lld..%llu\n", MIN_OF(uint8_t), MAX_OF(uint8_t)); 
    printf("int8_t = %lld..%llu\n", MIN_OF(int8_t), MAX_OF(int8_t)); 
    printf("uint16_t = %lld..%llu\n", MIN_OF(uint16_t), MAX_OF(uint16_t)); 
    printf("int16_t = %lld..%llu\n", MIN_OF(int16_t), MAX_OF(int16_t)); 
    printf("int = %lld..%llu\n", MIN_OF(int), MAX_OF(int)); 
    printf("long int = %lld..%llu\n", MIN_OF(long int), MAX_OF(long int)); 
    printf("long long int = %lld..%llu\n", MIN_OF(long long int), MAX_OF(long long int)); 
    printf("off_t = %lld..%llu\n", MIN_OF(off_t), MAX_OF(off_t)); 

    return 0; 
} 
0

valori MIN e MAX di qualsiasi tipo di dati integer può essere calcolato senza utilizzare alcuna funzione di libreria come sotto e la stessa logica può essere applicata ad altri tipi interi short, int e long.

printf("Signed Char : MIN -> %d & Max -> %d\n", ~(char)((unsigned char)~0>>1), (char)((unsigned char)~0 >> 1)); 
printf("Unsigned Char : MIN -> %u & Max -> %u\n", (unsigned char)0, (unsigned char)(~0)); 
4

valore massimo di qualsiasi unsigned tipo integrale: (~(t)0)

massima valore di qualsiasi firmato tipo integrale: Se si dispone di una variante non firmato di tipo t, ((t)((~(unsigned t)0)>>1)) vi darà il risultato più veloce che ti serve (vedi esempio nel codice sorgente del kernel di Linux di cui sotto). Altrimenti, dovresti probabilmente usare (~(1ULL<<(sizeof(t)*CHAR_BIT-1))).

minimo Valore di qualsiasi firmato tipo integrale: Devi conoscere la rappresentazione numero con segno della vostra macchina. La maggior parte delle macchine utilizza il complemento a 2, quindi -(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))-1 funzionerà per te.

Per rilevare se la macchina utilizza il complemento a 2, rilevare se (~(t)0U) e (t)(-1) rappresentano la stessa cosa. Quindi, combinato con sopra:

((~(t)0U) == (t)(-1) ? -(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))-1 : 
         -(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))) 

fornirà il valore minimo di qualsiasi tipo integrale firmato. (In realtà ci sono altre rappresentazioni di questo se si conosce la rappresentazione del complemento di 2. Ad esempio (t)(1ULL<<(sizeof(t)*CHAR_BIT-1)) dovrebbe essere equivalente a (t)(-(~(1ULL<<(sizeof(t)*CHAR_BIT-1)))-1).)

Ad esempio: (~ (size_t) 0) fornisce il valore massimo di size_t. (E indovinate un po ', questo è il modo SIZE_MAX è #defined in Linux kernel source code.)

Uno avvertimento però: tutte queste espressioni usare il tipo di fusione e quindi non funzionano in condizionali preprocessore (# if ... #elif ... #endif e mi piace).

0

Per ottenere il valore massimo di un numero intero senza segno t la cui larghezza è almeno quella di unsigned int (altrimenti si verificano problemi con le promozioni di interi): ~(t) 0.

Se il tipo intero t firma, supponendo che non vi sono bit di riempimento, si può utilizzare:

((((t) 1 << (sizeof(t) * CHAR_BIT - 2)) - 1) * 2 + 1) 

Il vantaggio di questa formula è che non si basa su qualche versione senza segno di t (o un tipo più grande), che può essere sconosciuto o non disponibile (anche uintmax_t potrebbe non essere sufficiente con estensioni non standard). Esempio con 6 bit (non è possibile in pratica, solo per leggibilità):

010000 (t) 1 << (sizeof(t) * CHAR_BIT - 2) 
001111 - 1 
011110 * 2 
011111 + 1 

in complemento a due, il valore minimo è l'opposto del valore massimo, meno 1 (in altre rappresentazioni interi consentito dalla ISO C standard, questo è esattamente l'opposto del valore massimo).

3
#include<stdio.h> 

int main(void) 
{ 
    printf("Minimum Signed Char %d\n",-(char)((unsigned char) ~0 >> 1) - 1); 
    printf("Maximum Signed Char %d\n",(char) ((unsigned char) ~0 >> 1)); 

    printf("Minimum Signed Short %d\n",-(short)((unsigned short)~0 >>1) -1); 
    printf("Maximum Signed Short %d\n",(short)((unsigned short)~0 >> 1)); 

    printf("Minimum Signed Int %d\n",-(int)((unsigned int)~0 >> 1) -1); 
    printf("Maximum Signed Int %d\n",(int)((unsigned int)~0 >> 1)); 

    printf("Minimum Signed Long %ld\n",-(long)((unsigned long)~0 >>1) -1); 
    printf("Maximum signed Long %ld\n",(long)((unsigned long)~0 >> 1)); 

    /* Unsigned Maximum Values */ 

    printf("Maximum Unsigned Char %d\n",(unsigned char)~0); 
    printf("Maximum Unsigned Short %d\n",(unsigned short)~0); 
    printf("Maximum Unsigned Int %u\n",(unsigned int)~0); 
    printf("Maximum Unsigned Long %lu\n",(unsigned long)~0); 

    return 0; 
} 
+0

Possiamo semplicemente ottenere il valore più alto del tipo di dati senza segno e sottrarlo dal valore massimo per ottenere il valore minimo. –

+0

Questa è una grande risposta indipendente dal sistema che dimostra una comprensione dei tipi, della memoria e, naturalmente, degli operatori bit a bit C. –

Problemi correlati