Ad esempio:
sizeof(char*)
restituisce 4. Come fa int*
, long long*
tutto ciò che ho provato. Ci sono delle eccezioni a questo?
Ad esempio:
sizeof(char*)
restituisce 4. Come fa int*
, long long*
tutto ciò che ho provato. Ci sono delle eccezioni a questo?
Risposte:
La garanzia che ottieni è quella sizeof(char) == 1
. Non ci sono altre garanzie, inclusa quella sizeof(int *) == sizeof(double *)
.
In pratica, i puntatori avranno la dimensione 2 su un sistema a 16 bit (se riesci a trovarne uno), 4 su un sistema a 32 bit e 8 su un sistema a 64 bit, ma non c'è nulla da guadagnare facendo affidamento su un dato taglia.
Anche su una semplice piattaforma x86 a 32 bit, puoi ottenere una varietà di dimensioni del puntatore, prova questo per un esempio:
struct A {};
struct B : virtual public A {};
struct C {};
struct D : public A, public C {};
int main()
{
cout << "A:" << sizeof(void (A::*)()) << endl;
cout << "B:" << sizeof(void (B::*)()) << endl;
cout << "D:" << sizeof(void (D::*)()) << endl;
}
In Visual C ++ 2008, ottengo 4, 12 e 8 per le dimensioni della funzione pointer-to-member.
Raymond Chen ne ha parlato qui .
Solo un'altra eccezione all'elenco già pubblicato. Su piattaforme a 32 bit, i puntatori possono richiedere 6, non 4 byte:
#include <stdio.h>
#include <stdlib.h>
int main() {
char far* ptr; // note that this is a far pointer
printf( "%d\n", sizeof( ptr));
return EXIT_SUCCESS;
}
Se compili questo programma con Open Watcom ed eseguilo, otterrai 6, poiché i puntatori lontani che supporta sono costituiti da valori offset di 32 bit e segmenti di 16 bit
se si sta compilando per un computer a 64 bit, potrebbe essere 8.
sizeof(char*)==1
? Sei sicuro? Non intendi size(char)==1
?
Tecnicamente parlando, lo standard C garantisce solo che sizeof (char) == 1, e il resto dipende dall'implementazione. Ma sulle moderne architetture x86 (ad es. Chip Intel / AMD) è abbastanza prevedibile.
Probabilmente hai sentito i processori descritti come 16-bit, 32-bit, 64-bit, ecc. Questo di solito significa che il processore usa N-bit per numeri interi. Poiché i puntatori memorizzano gli indirizzi di memoria e gli indirizzi di memoria sono numeri interi, ciò indica effettivamente quanti bit verranno utilizzati per i puntatori. La dimensione di solito viene misurata in byte, quindi il codice compilato per i processori a 32 bit riporterà la dimensione dei puntatori a 4 (32 bit / 8 bit per byte) e il codice per i processori a 64 bit riporterà la dimensione dei puntatori a 8 (64 bit / 8 bit per byte). Ecco da dove viene la limitazione di 4 GB di RAM per processori a 32 bit: se ogni indirizzo di memoria corrisponde a un byte, per indirizzare più memoria sono necessari numeri interi superiori a 32 bit.
La dimensione del puntatore dipende fondamentalmente dall'architettura del sistema in cui è implementato. Ad esempio, la dimensione di un puntatore a 32 bit è 4 byte (32 bit) e 8 byte (64 bit) in macchine a 64 bit. I tipi di bit in una macchina non sono altro che indirizzo di memoria, che può avere. Le macchine a 32 bit possono avere 2^32
lo spazio degli indirizzi e le macchine a 64 bit possono avere gli 2^64
spazi degli indirizzi. Quindi un puntatore (variabile che punta a una posizione di memoria) dovrebbe essere in grado di puntare a qualsiasi indirizzo di memoria ( 2^32 for 32 bit and 2^64 for 64 bit
) che detiene una macchina.
Per questo motivo vediamo che la dimensione di un puntatore è di 4 byte in una macchina a 32 bit e 8 byte in una macchina a 64 bit.
Oltre alle differenze di 16/32/64 bit possono verificarsi anche cose più strane.
Ci sono state macchine in cui sizeof (int *) avrà un valore, probabilmente 4 ma in cui sizeof (char *) è più grande. Le macchine che indirizzano naturalmente le parole anziché i byte devono "aumentare" i puntatori di caratteri per specificare quale porzione della parola vuoi veramente per implementare correttamente lo standard C / C ++.
Questo è ora molto insolito poiché i progettisti hardware hanno imparato il valore dell'indirizzamento dei byte.
void*
e char*
sono gestiti nel software e sono aumentati con un offset di 3 bit all'interno della parola - ma poiché in realtà non esiste uno spazio di indirizzi a 64 bit, l'offset è memorizzato nei 3 bit di ordine superiore del 64-bit parola. Quindi char*
e int*
hanno le stesse dimensioni, ma hanno rappresentazioni interne diverse - e il codice che presuppone che i puntatori siano "realmente" solo i numeri interi possono fallire male.
I puntatori a 8 e 16 bit sono utilizzati nella maggior parte dei microcontrollori a basso profilo. Ciò significa che ogni lavatrice, micro, frigorifero, TV più vecchie e persino automobili.
Si potrebbe dire che non hanno nulla a che fare con la programmazione nel mondo reale. Ma ecco un esempio reale: Arduino con 1-2-4k di RAM (a seconda del chip) con puntatori a 2 byte.
È recente, economico, accessibile a tutti e vale la pena codificarlo.
Oltre a ciò che la gente ha detto sui sistemi a 64 bit (o qualsiasi altra cosa), esistono altri tipi di puntatori oltre al puntatore all'oggetto.
Un puntatore al membro può avere quasi tutte le dimensioni, a seconda di come sono implementate dal compilatore: non sono necessariamente tutte uguali. Prova un puntatore a membro di una classe POD, quindi un puntatore a membro ereditato da una delle classi di base di una classe con più basi. Che divertimento.
Da quello che ricordo, si basa sulla dimensione di un indirizzo di memoria. Quindi su un sistema con uno schema di indirizzi a 32 bit, sizeof restituirà 4, dato che sono 4 byte.
sizeof (unsigned int) == sizeof (signed int)
, questo requisito si trova in 3.9.1 / 3. "Per ogni dello standard intero con segno tipi, esiste una corrispondente (ma differente) tipo intero senza segno serie: unsigned char
, unsigned short int
, unsigned int
, unsigned long int
, e unsigned long long int
, ognuno dei quali occupa la stessa quantità di stoccaggio ed ha gli stessi requisiti di allineamento della corrispondente intero con segno tipo "
In generale, sizeof (praticamente qualsiasi cosa) cambierà quando si compila su piattaforme diverse. Su una piattaforma a 32 bit, i puntatori hanno sempre le stesse dimensioni. Su altre piattaforme (64 bit è l'esempio ovvio) questo può cambiare.
No, la dimensione di un puntatore può variare a seconda dell'architettura. Vi sono numerose eccezioni.
La dimensione del puntatore e int è di 2 byte nel compilatore Turbo C sulla macchina Windows a 32 bit.
Quindi la dimensione del puntatore è specifica del compilatore. Ma generalmente la maggior parte dei compilatori sono implementati per supportare variabili di puntatore a 4 byte in 32 bit e variabili di puntatore da 8 byte in computer a 64 bit).
Quindi la dimensione del puntatore non è la stessa in tutte le macchine.
Il motivo per cui la dimensione del puntatore è di 4 byte è perché si sta compilando per un'architettura a 32 bit. Come ha sottolineato FryGuy, su un'architettura a 64 bit ne vedresti 8.
In Win64 (Cygwin GCC 5.4) , vediamo l'esempio seguente:
Innanzitutto, prova la seguente struttura:
struct list_node{
int a;
list_node* prev;
list_node* next;
};
struct test_struc{
char a, b;
};
Il codice di prova è di seguito:
std::cout<<"sizeof(int): "<<sizeof(int)<<std::endl;
std::cout<<"sizeof(int*): "<<sizeof(int*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(double): "<<sizeof(double)<<std::endl;
std::cout<<"sizeof(double*): "<<sizeof(double*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(list_node): "<<sizeof(list_node)<<std::endl;
std::cout<<"sizeof(list_node*): "<<sizeof(list_node*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(test_struc): "<<sizeof(test_struc)<<std::endl;
std::cout<<"sizeof(test_struc*): "<<sizeof(test_struc*)<<std::endl;
L'output è inferiore:
sizeof(int): 4
sizeof(int*): 8
sizeof(double): 8
sizeof(double*): 8
sizeof(list_node): 24
sizeof(list_node*): 8
sizeof(test_struc): 2
sizeof(test_struc*): 8
Puoi vederlo a 64 bit, sizeof(pointer)
è 8
.
Un puntatore è solo un contenitore per un indirizzo. Su una macchina a 32 bit, l'intervallo di indirizzi è di 32 bit, quindi un puntatore sarà sempre di 4 byte. Su una macchina a 64 bit, se si dispone di un intervallo di indirizzi di 64 bit, un puntatore sarà di 8 byte.
Solo per completezza e interesse storico, nel mondo a 64 bit c'erano diverse convenzioni di piattaforme sulle dimensioni di tipi lunghi e lunghi, chiamati LLP64 e LP64, principalmente tra sistemi di tipo Unix e Windows. Un vecchio standard chiamato ILP64 rendeva anche int = 64-bit di larghezza.
Microsoft ha mantenuto LLP64 dove longlong = 64 bit di larghezza, ma è rimasto a lungo a 32, per facilitare il porting.
Type ILP64 LP64 LLP64
char 8 8 8
short 16 16 16
int 64 32 32
long 64 64 32
long long 64 64 64
pointer 64 64 64