Zum Beispiel:
sizeof(char*)
zurück 4. Wie hat int*
, long long*
alles, was ich versucht habe. Gibt es hiervon Ausnahmen?
Zum Beispiel:
sizeof(char*)
zurück 4. Wie hat int*
, long long*
alles, was ich versucht habe. Gibt es hiervon Ausnahmen?
Antworten:
Die Garantie, die Sie erhalten, ist die sizeof(char) == 1
. Es gibt keine anderen Garantien, einschließlich keiner Garantie dafür sizeof(int *) == sizeof(double *)
.
In der Praxis haben Zeiger auf einem 16-Bit-System (falls vorhanden) die Größe 2, auf einem 32-Bit-System die Größe 4 und auf einem 64-Bit-System die Größe 8, aber es gibt nichts zu gewinnen, wenn man sich auf ein bestimmtes System verlässt Größe.
Selbst auf einer einfachen x86 32-Bit-Plattform können Sie eine Vielzahl von Zeigergrößen erhalten. Probieren Sie dies als Beispiel aus:
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;
}
Unter Visual C ++ 2008 erhalte ich 4, 12 und 8 für die Größe der Zeiger-auf-Mitglied-Funktion.
Raymond Chen hat hier darüber gesprochen .
Nur eine weitere Ausnahme von der bereits veröffentlichten Liste. Auf 32-Bit-Plattformen können Zeiger 6, nicht 4 Bytes benötigen:
#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;
}
Wenn Sie dieses Programm mit Open Watcom kompilieren und ausführen, erhalten Sie 6, da die von ihm unterstützten Fernzeiger aus 32-Bit-Offset- und 16-Bit-Segmentwerten bestehen
Wenn Sie für einen 64-Bit-Computer kompilieren, kann dies 8 sein.
sizeof(char*)==1
? Bist du sicher? Meinst du nicht size(char)==1
?
Technisch gesehen garantiert der C-Standard nur die Größe von (char) == 1, und der Rest hängt von der Implementierung ab. Auf modernen x86-Architekturen (z. B. Intel / AMD-Chips) ist dies jedoch ziemlich vorhersehbar.
Sie haben wahrscheinlich Prozessoren gehört, die als 16-Bit, 32-Bit, 64-Bit usw. beschrieben wurden. Dies bedeutet normalerweise, dass der Prozessor N-Bit für Ganzzahlen verwendet. Da Zeiger Speicheradressen speichern und Speicheradressen Ganzzahlen sind, gibt dies effektiv an, wie viele Bits für Zeiger verwendet werden sollen. sizeof wird normalerweise in Bytes gemessen, sodass für 32-Bit-Prozessoren kompilierter Code eine Zeigergröße von 4 (32 Bit / 8 Bit pro Byte) und Code für 64-Bit-Prozessoren eine Größe von 8 Zeigern angibt (64 Bit / 8 Bit pro Byte). Hier liegt die Beschränkung von 4 GB RAM für 32-Bit-Prozessoren. Wenn jede Speicheradresse einem Byte entspricht, benötigen Sie Ganzzahlen, die größer als 32 Bit sind, um mehr Speicher zu adressieren.
Die Größe des Zeigers hängt im Wesentlichen von der Architektur des Systems ab, in dem er implementiert ist. Beispielsweise beträgt die Größe eines Zeigers in 32-Bit 4 Byte (32 Bit) und 8 Byte (64 Bit) in 64-Bit-Maschinen. Die Bittypen in einer Maschine sind nichts anderes als eine Speicheradresse, die sie haben kann. 32-Bit-Maschinen können einen 2^32
Adressraum haben und 64-Bit-Maschinen können bis zu 2^64
Adressräume haben. Ein Zeiger (eine Variable, die auf einen Speicherort zeigt) sollte also auf eine der Speicheradressen ( 2^32 for 32 bit and 2^64 for 64 bit
) verweisen können , die eine Maschine enthält.
Aus diesem Grund beträgt die Größe eines Zeigers in einer 32-Bit-Maschine 4 Byte und in einer 64-Bit-Maschine 8 Byte.
Zusätzlich zu den 16/32/64 Bitunterschieden können noch seltsamere Dinge auftreten.
Es gab Maschinen, bei denen sizeof (int *) einen Wert hat, wahrscheinlich 4, bei denen sizeof (char *) jedoch größer ist. Maschinen, die natürlich Wörter anstelle von Bytes adressieren, müssen Zeichenzeiger "erweitern", um anzugeben, welchen Teil des Wortes Sie wirklich möchten, um den C / C ++ - Standard ordnungsgemäß zu implementieren.
Dies ist jetzt sehr ungewöhnlich, da Hardware-Designer den Wert der Byteadressierbarkeit gelernt haben.
void*
und char*
werden in Software behandelt und mit einem 3-Bit-Offset innerhalb des Wortes erweitert. Da jedoch kein 64-Bit-Adressraum vorhanden ist, wird der Offset in den höherwertigen 3 Bits des 64-Bit-Adressraums gespeichert Wort. Also char*
und int*
sind gleich groß, haben aber unterschiedliche interne Darstellungen - und Code, der davon ausgeht, dass Zeiger "wirklich" sind, nur ganze Zahlen können schlecht ausfallen.
8-Bit- und 16-Bit-Zeiger werden in den meisten Low-Profile-Mikrocontrollern verwendet. Das bedeutet jede Waschmaschine, jedes Mikro, jeden Kühlschrank, jeden älteren Fernseher und sogar jedes Auto.
Man könnte sagen, diese haben nichts mit realer Programmierung zu tun. Aber hier ist ein Beispiel aus der Praxis: Arduino mit 1-2-4k RAM (je nach Chip) mit 2 Byte Zeigern.
Es ist neu, billig, für jedermann zugänglich und es lohnt sich, dafür zu programmieren.
Zusätzlich zu dem, was die Leute über 64-Bit-Systeme (oder was auch immer) gesagt haben, gibt es andere Arten von Zeigern als Zeiger auf Objekt.
Ein Zeiger auf ein Mitglied kann fast jede Größe haben, je nachdem, wie sie von Ihrem Compiler implementiert werden: Sie sind nicht unbedingt alle gleich groß. Versuchen Sie es mit einem Zeiger auf ein Mitglied einer POD-Klasse und anschließend mit einem Zeiger auf ein Mitglied, das von einer der Basisklassen einer Klasse mit mehreren Basen geerbt wurde. Was für ein Spaß.
Soweit ich mich erinnere, basiert es auf der Größe einer Speicheradresse. Auf einem System mit einem 32-Bit-Adressschema gibt sizeof 4 zurück, da dies 4 Bytes sind.
sizeof (unsigned int) == sizeof (signed int)
ist diese Anforderung in 3.9.1 / 3 enthalten. „Für jede der Standard Integer - Typen signiert, existiert eine entsprechende (jedoch unterschiedlichen) -Standard unsigned integer Typ: unsigned char
, unsigned short int
, unsigned int
, unsigned long int
, und unsigned long long int
, von denen jedes nimmt die gleiche Menge an Speicher und hat die gleiche Ausrichtung Anforderungen wie die Integer - Typ signiert entsprechende "
Im Allgemeinen ändert sich sizeof (so ziemlich alles), wenn Sie auf verschiedenen Plattformen kompilieren. Auf einer 32-Bit-Plattform haben Zeiger immer die gleiche Größe. Auf anderen Plattformen (64 Bit ist das offensichtliche Beispiel) kann sich dies ändern.
Nein, die Größe eines Zeigers kann je nach Architektur variieren. Es gibt zahlreiche Ausnahmen.
Die Größe von Zeiger und int beträgt im Turbo C-Compiler auf einem 32-Bit-Windows-Computer 2 Byte.
Die Größe des Zeigers ist also compilerspezifisch. Im Allgemeinen sind die meisten Compiler jedoch so implementiert, dass sie 4-Byte-Zeigervariablen in 32-Bit- und 8-Byte-Zeigervariablen in 64-Bit-Maschinen unterstützen.
Die Größe des Zeigers ist also nicht bei allen Maschinen gleich.
Der Grund, warum Ihr Zeiger 4 Byte groß ist, liegt darin, dass Sie für eine 32-Bit-Architektur kompilieren. Wie FryGuy betonte, würden Sie auf einer 64-Bit-Architektur 8 sehen.
In Win64 (Cygwin GCC 5.4) sehen wir uns das folgende Beispiel an:
Testen Sie zunächst die folgende Struktur:
struct list_node{
int a;
list_node* prev;
list_node* next;
};
struct test_struc{
char a, b;
};
Der Testcode ist unten:
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;
Die Ausgabe ist unten:
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
Sie können sehen, dass in 64-Bit sizeof(pointer)
ist 8
.
Ein Zeiger ist nur ein Container für eine Adresse. Auf einem 32-Bit-Computer beträgt Ihr Adressbereich 32 Bit, sodass ein Zeiger immer 4 Byte lang ist. Auf einem 64-Bit-Computer mit einem Adressbereich von 64 Bit beträgt der Zeiger 8 Byte.
Der Vollständigkeit halber und aus historischen Gründen gab es in der 64-Bit-Welt unterschiedliche Plattformkonventionen für die Größen von langen und langen langen Typen mit den Namen LLP64 und LP64, hauptsächlich zwischen Unix-Systemen und Windows. Ein alter Standard namens ILP64 hat auch int = 64-Bit breit gemacht.
Microsoft hat LLP64 beibehalten, wobei longlong = 64 Bit breit ist, aber zur einfacheren Portierung lange bei 32 geblieben ist.
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