2016-03-07 29 views
64

È sempre vero che long int (che per quanto ho capito è un sinonimo di long) è 4 byte?Posso supporre che la dimensione di long int sia sempre di 4 byte?

Posso contare su questo? In caso contrario, potrebbe essere vero per un sistema operativo basato su POSIX?

+12

Solo per ricordare a voi ragazzi che 'sizeof' prende in considerazione il riempimento e l'allineamento. È conforme allo standard avere un 'sizeof (unsigned long)' di 8 byte ma l'overflow si comporta come 4 byte. È sbagliato tentare di usare 'sizeof' e' CHAR_BITS' per calcolare il limite di un tipo intero. Usa 'limits.h' quando dovrebbe essere usato. – user3528438

+11

Dovresti davvero leggere il (abbreviato prima, quindi la versione completa del) C-faq, che ha avuto origine su Usenet in un momento in cui era * il * luogo in cui le persone con conoscenza su un argomento si riunivano nello stesso luogo (ora, è diffuso tra diversi siti ...), e quindi ha portato a domande incredibilmente approfondite e ben fatte. Vedi http://c-faq.com/versions.html. Leggendolo si aprirà gli occhi su questa domanda e su dozzine in più probabilmente non sai nemmeno che devi ancora sapere (sezione 5 - puntatori nulli - è uno che contiene le FAQ Sono rimasto scioccato (e grato) a scoprire) –

+7

no, è 8 sul mio pc – RiaD

risposta

102

Gli standard non dicono nulla per quanto riguarda le dimensioni esatte di tutti i tipi di interi oltre a char. In genere, long è a 32 bit su sistemi a 32 bit e 64 bit su sistemi a 64 bit.

Lo standard specifica tuttavia una dimensione minima. Dalla sezione 5.2.4.2.1 del C Standard:

I valori riportati di seguito sono sostituiti da espressioni costanti adatti all'uso nella #if direttive al preprocessore. Inoltre, tranne CHAR_BIT e MB_LEN_MAX, i seguenti prodotti sono sostituiti da espressioni che hanno lo stesso tipo come farebbe un un'espressione che è un oggetto del tipo corrispondente convertita secondo promozioni interi. I rispettivi valori definiti dall'implementazione devono essere uguali o maggiori di grandezza (valore assoluto) a quelli mostrati, con lo stesso segno.

...

  • valore minimo per un oggetto di tipo long int

    LONG_MIN -2147483647 // - (2^31-1)

  • valore massimo per un oggetto di tipo long int

    LONG_MAX +2147483647 // 2^31-1

Questo dice che un long intdeve essere un minimo di 32 bit, ma può essere più grande. Su una macchina in cui CHAR_BIT è 8, questo dà una dimensione minima in byte di 4. Tuttavia sulla macchina con ad es. CHAR_BIT uguale a 16, un long int potrebbe essere lungo 2 byte.

Ecco un esempio del mondo reale.Per il codice seguente:

#include <stdio.h> 

int main() 
{ 
    printf("sizeof(long) = %zu\n", sizeof(long)); 
    return 0; 
} 

uscita su Debian 7 i686:

sizeof (long) = 4

uscita su CentOS 7 x64:

sizeof (long) = 8

Quindi no, non è possibile formulare ipotesi sulla dimensione. Se è necessario un tipo di dimensione specifica, è possibile utilizzare i tipi definiti in stdint.h. Definisce le seguenti tipologie:

  • int8_t: segno a 8 bit
  • uint8_t: 8 bit senza segno
  • int16_t: 16 bit
  • uint16_t: 16 bit senza segno
  • int32_t: firmato 32-bit
  • uint32_t: senza segno 32 bit
  • int64_t: segno a 64 bit
  • uint64_t: 64 bit unsigned

L'intestazione stdint.h è descritto nella sezione 7.20 della norma, con tipi larghezza esatta in sezione 7.20.1.1. Lo standard afferma che questi typedef sono opzionali, ma esistono nella maggior parte delle implementazioni.

+0

Questo typedef come 'uint64_t' non fa parte dello standard prima di C11. Forse dovresti dirlo. – JojOatXGME

+4

Ma questi typedef sono nello standard! Solo l'implementazione definisce se esistono realmente e quali tipi rappresentano! – Vincent

+1

@JojOatXGME 'stdint.h' esiste dal C99. – user694733

20

Utilizzare il codice sizeof(long int) e verificare la dimensione. Ti fornirà la dimensione di long int in byte sul sistema che stai attualmente lavorando. La risposta della tua domanda in particolare è NO. Non è garantito da nessuna parte in C o in POSIX o ovunque.

+2

IMO, che non risponde alla domanda. – nouney

+6

In realtà mi ha aiutato :) – Elimination

+0

@nouney come affermare che non esiste una dimensione esatta garantita dagli standard C, o che gli standard POSIX non rispondono alla domanda? non è la risposta migliore, ma certamente non è sbagliata. – Leliel

38

No, né lo standard C né POSIX lo garantiscono e infatti lo most Unix-like 64-bit platforms dispone di un valore di 64 bit (8 byte) long.

+0

Ints sulla maggior parte delle piattaforme a 32 bit e superiori sono a 32 bit (AFAIK, comunque), quale sarebbe il punto di avere un lungo che è la stessa dimensione di un int? Sul mio sistema (Intel, 64-bit Linux, gcc) è 32 per int, 64 per molto tempo. – jamesqf

+7

@jamesqf: nella stragrande maggioranza delle piattaforme rilasciate tra il 1980 e il 2005, breve era 16 bit, lungo 32 bit e "int" 16 o 32 bit, a vantaggio dell'implementazione. Avere tipi di dimensione fissa per i tipi a 16 e 32 bit prima che C99 aggiungesse stdint.h era utile. Come un ulteriore fattore complicante aggiuntivo con quest'ultimo, tuttavia, su un sistema con "int" a 32 bit, int32_t potrebbe essere compatibile con "int" o con "long", ma le implementazioni conformi non sono consentite per renderlo compatibile con entrambi. – supercat

14

Come sottolineato da @delnan, le implementazioni POSIX mantengono le dimensioni di long e int come non specificato e spesso differiscono tra i sistemi a 32 bit e 64 bit.

La lunghezza del long è in gran parte hardware correlati (spesso corrispondente alla dimensione dei registri dati della CPU e, talvolta, altri problemi relativi al software come la progettazione del sistema operativo e ABI interfacciamento).

Per semplificare la mente, sizeof non è una funzione, ma una direttiva del compilatore *, quindi il codice non utilizza le operazioni quando si utilizza sizeof - è lo stesso che scrivere un numero, solo che è portatile.

uso:

sizeof(long int) 

* Come Dave sottolineato nei commenti, sizeof sarà calcolato a runtime quando è impossibile calcolare il valore durante la compilazione, come quando si usa array di lunghezza variabile.

Inoltre, come indicato in un altro commento, sizeof prende in considerazione il padding e l'allineamento utilizzati dall'implementazione, il che significa che i byte effettivi in ​​uso potrebbero essere diversi dalla dimensione in memoria (questo potrebbe essere importante quando il bit shifting) .

Se si cercano variabili di dimensione byte specifiche, considerare l'utilizzo di una matrice di byte o (presumibilmente di essere supportati) i tipi definiti da C99 in stdint.h, come suggerito da @ dbush.

+3

Non (solo) hardware. È possibile eseguire un Linux a 32 bit su hardware a 64 bit e si può persino utilizzare l'ABI x32 in cui i tipi di dati sono dimensionati come su hardware a 32 bit, ma l'hardware viene effettivamente eseguito in modalità a 64 bit. – delnan

+0

@delnan, sì, è vero. Probabilmente dovrei chiarirlo cambiando 'solito' a' principalmente 'e aggiungendo un'informazione tra parentesi. – Myst

+0

@delnan, non volevo scavalcare la tua risposta, ho solo pensato che sarebbe meglio chiarire che 'sizeof' è una direttiva del compilatore, per rimuovere tutti i motivi percepiti che chiunque potrebbe avere per indovinare le dimensioni. – Myst

8

Il compilatore determina la dimensione in base al tipo di hardware e sistema operativo.

Quindi, non si dovrebbero formulare ipotesi sulla dimensione.

12

Quando abbiamo implementato C su ICL Series 39 hardware, abbiamo preso lo standard in parola e mappati i tipi di dati alla rappresentazione naturale che l'architettura della macchina, che era short = 32 bit, int = 64 bit, long = 128 bit.

Ma abbiamo scoperto che nessuna applicazione C seria funzionava; tutti hanno assunto la mappatura short = 16, int = 32, long = 64 e abbiamo dovuto modificare il compilatore per supportarlo.

Quindi, qualunque sia lo standard ufficiale, per molti anni tutti sono convergenti su long = 64 bit e non è probabile che cambi.

+0

Davvero? Almeno su GCC/Glibc/GNU/Linux, le piattaforme sembrano convergere su int = 32, long long = 64, long = dimensione della parola nativa (o 32 o 64) e certamente non lunga = 64. Es. su x86, che non è esattamente un'architettura di nicchia, è lungo 32 bit. OSX, Solaris, z/OS, SysV sono altri sistemi operativi che seguono questa convenzione. –

+0

Per un sistema ancora più diffuso di OSX, Linux, z/OS o SysV, c'è Windows, che ha ancora un'altra convenzione diversa dalla tua (sempre 64) o quella (sempre uguale a un puntatore), vale a dire sempre 32 bit. –

+0

IMHO, il rimedio corretto sarebbe avere un mezzo standard con il quale il codice può specificare quale tipo di "int", "long", ecc. Sono richiesti all'interno di determinati contesti [tipicamente per file, in modo che un file di intestazione che dichiari una funzione poiché accettare "int" avrà sempre lo stesso significato]. Avere un sistema a 64 bit emulare un "int" a 16 o 32 bit dovrebbe essere abbastanza semplice, e sarebbe probabilmente più affidabile di cercare di adattare il codice dato tutte le piccole sfumature in C (come il fatto che su un 64 -bit system, la moltiplicazione modulare uint32_t non funziona per tutti i valori). – supercat

9

standard non dice nulla delle dimensioni di long int, quindi dipende dall'ambiente che si sta utilizzando.

Per ottenere le dimensioni di long int sul proprio ambiente è possibile utilizzare l'operatore sizeof e ottenere le dimensioni di long int. Qualcosa di simile

sizeof(long int) 

C standard richiede solo i seguenti punti relativi alle dimensioni dei tipi

  • int> = 16 bit,
  • lunghe> = 32 bit,
  • lungo tempo (dal C99)> = 64 bit
  • sizeof (char) < = sizeof (breve) < = sizeof (int) < = sizeof (long) < = sizeof (long lunghi)
  • sizeof (char) == 1
  • CHAR_BIT> = 8

I restanti sono implementazioni definiti, quindi non è sorpresa se quella incontrata alcuni sistemi dove int ha 18/24/36/60 bit, il proprio modulo complemento firmato , sizeof (char) == sizeof (breve) == sizeof (int) == sizeof (long) == 4, 48-bit long o 9-bit char come le architetture esotiche che interessano i comitati standard e l'elenco delle piattaforme supportate dallo standard C

Il punto su long int above è completamente sbagliato.La maggior parte delle implementazioni di Linux/Unix si definiscono a lungo come un tipo a 64 bit ma sono solo 32 bit in Windows perché utilizzano modelli di dati diversi (dai un'occhiata alla tabella qui 64-bit computing) e questo indipendentemente dai 32 o 64 bit Versione del sistema operativo.

Source

1

Da Usrmisc's Blog:

Lo standard lascia completamente fino al compilatore, che significa anche lo stesso compilatore può rendere dipendono opzioni e architettura di destinazione.

Quindi non è possibile.

Incidentalmente long int è lo stesso di long.

0

Risposta breve: No! Non è possibile fare supposizioni fisse sulle dimensioni di long int. Perché, lo standard (C standard o POSIX) non documenta la dimensione di long int (come più volte sottolineato). Solo per fornire un contro esempio alla tua convinzione, la maggior parte dei sistemi a 64 bit ha long di dimensione 64! Per massimizzare la portabilità, utilizzare sizeof in modo appropriato.

Utilizzare sizeof(long int) per verificare le dimensioni, restituisce le dimensioni di long in byte. Il valore dipende dal sistema o dall'ambiente; nel senso, il compilatore determina la dimensione in base all'hardware e al sistema operativo.