Örneğin:
sizeof(char*)
As gelmez 4. döndürür int*
, long long*
ben denedim her şey o. Bunun istisnası var mı?
Örneğin:
sizeof(char*)
As gelmez 4. döndürür int*
, long long*
ben denedim her şey o. Bunun istisnası var mı?
Yanıtlar:
Aldığınız garanti şudur sizeof(char) == 1
. Bunun garantisi de dahil olmak üzere başka garanti yoktur sizeof(int *) == sizeof(double *)
.
Pratikte, işaretçiler 16 bitlik bir sistemde 2 boyutunda (bir tane bulabilirseniz), 32 bitlik bir sistemde 4 ve 64 bitlik bir sistemde 8 olacaktır, ancak belirli bir verilere dayanarak kazanılacak hiçbir şey yoktur. boyut.
Düz bir x86 32 bit platformda bile, çeşitli işaretçi boyutları elde edebilirsiniz, bunu bir örnek için deneyin:
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;
}
Visual C ++ 2008 altında, işaretçiler-üye-işlevinin boyutları için 4, 12 ve 8 olsun.
Raymond Chen burada bunun hakkında konuştu .
Zaten gönderilen listeye bir istisna daha. 32 bit platformlarda, işaretçiler 4 değil , 6 bayt alabilir:
#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;
}
Bu programı Open Watcom ile derlerseniz ve çalıştırırsanız, 6 elde edersiniz, çünkü desteklediği uzak işaretçiler 32 bit ofset ve 16 bit segment değerlerinden oluşur
64 bit bir makine için derliyorsanız, 8 olabilir.
sizeof(char*)==1
? Emin misiniz? Bunu mu demek istediniz size(char)==1
?
Teknik olarak konuşursak, C standardı sadece sizeof (char) == 1 olduğunu garanti eder ve gerisi uygulamaya bağlıdır. Ancak modern x86 mimarilerinde (örn. Intel / AMD yongaları) oldukça tahmin edilebilir.
Muhtemelen 16 bit, 32 bit, 64 bit vb. Olarak tanımlanan işlemcileri duymuşsunuzdur. Bu genellikle işlemcinin tamsayılar için N-bitleri kullandığı anlamına gelir. İşaretçiler bellek adreslerini depoladığından ve bellek adresleri tamsayı olduğundan, işaretçiler için kaç bit kullanılacağını etkin bir şekilde anlatır. sizeof genellikle bayt cinsinden ölçülür, bu nedenle 32 bit işlemciler için derlenen kod, işaretçi boyutunu 4 olarak bildirir (bayt başına 32 bit / 8 bit) ve 64 bit işlemciler için kod, işaretçi boyutunu 8 olarak bildirir (Bayt başına 64 bit / 8 bit). Bu, 32 bit işlemciler için 4GB RAM sınırlamasından kaynaklanır - her bellek adresi bir bayta karşılık geliyorsa, daha fazla belleği adreslemek için 32 bitten daha büyük tamsayılara ihtiyacınız vardır.
İşaretçinin boyutu temel olarak uygulandığı sistemin mimarisine bağlıdır. Örneğin, 32 bitlik bir işaretçinin boyutu 64 bitlik makinelerde 4 bayt (32 bit) ve 8 bayttır (64 bit). Bir makinedeki bit tipleri, sahip olabileceği bellek adresinden başka bir şey değildir. 32 bit makinelerde 2^32
adres alanı, 64 bit makinelerde adres alanı olabilir 2^64
. Dolayısıyla, bir işaretçi (bir bellek konumuna işaret eden değişken 2^32 for 32 bit and 2^64 for 64 bit
), makinelerin sahip olduğu bellek adreslerinden ( ) herhangi birini gösterebilmelidir .
Bu nedenle, işaretçinin boyutunun 32 bit makinede 4 bayt ve 64 bit makinede 8 bayt olduğunu görüyoruz.
16/32/64 bit farklarına ek olarak, daha tuhaf şeyler bile meydana gelebilir.
Sizeof (int *) 'nin bir değer, muhtemelen 4 olacağı, ancak sizeof (char *)' nın daha büyük olduğu makineler olmuştur. Bayt yerine kelimeleri doğal olarak adresleyen makinelerin, C / C ++ standardını düzgün bir şekilde uygulamak için kelimenin gerçekten hangi kısmını istediğinizi belirtmek için karakter işaretleyicilerini "artırması" gerekir.
Donanım tasarımcıları bayt adreslenebilirliğinin değerini öğrendiklerinden bu durum artık çok sıra dışı.
void*
ve char*
yazılımda işlenir ve sözcük içinde 3 bitlik bir ofset ile zenginleştirilir - ancak aslında 64 bitlik bir adres alanı olmadığından, ofset 64 bitin yüksek dereceli 3 bitinde depolanır sözcüğü. Yani char*
ve int*
aynı boyuttadır, ancak farklı dahili temsillere sahiptir - ve işaretçilerin "gerçekten" olduğunu varsayan kod, sadece tamsayılar başarısız olabilir.
Çoğu düşük profilli mikrodenetleyicide 8 bit ve 16 bit işaretçiler kullanılır. Bu, her çamaşır makinesi, mikro buzdolabı, eski TV'ler ve hatta arabalar anlamına gelir.
Bunların gerçek dünya programlama ile ilgisi olmadığını söyleyebilirsiniz. Ama işte gerçek bir dünya örneği: 1-2 baytlık koçlu Arduino (çipe bağlı olarak) 2 bayt işaretçisi.
Son zamanlarda, ucuz, herkes için erişilebilir ve değer kodlamaya değer.
İnsanların 64 bit (ya da her ne olursa olsun) sistemleri hakkında söylediklerine ek olarak, işaretçi-nesne dışında başka işaretçiler de vardır.
Bir işaretçi-üye, derleyiciniz tarafından nasıl uygulandıklarına bağlı olarak hemen hemen her boyutta olabilir: mutlaka aynı boyutta bile olmayabilirler. Bir POD sınıfının işaretçi-üyesini ve ardından birden çok tabanlı bir sınıfın temel sınıflarından birinden devralınan bir işaretçi-üyeyi deneyin. Ne komik.
Hatırladığım kadarıyla, bir bellek adresinin boyutuna dayanıyor. 32 bit adres şemasına sahip bir sistemde, sizeof 4 döndürür, çünkü bu 4 bayttır.
sizeof (unsigned int) == sizeof (signed int)
, bu gereksinim 3.9.1 / 3'te bulunur. "Tip tamsayıdır imzalanmış standart her biri için, karşılık gelen bir (fakat farklı), standart, işaretsiz tamsayı tipi vardır: unsigned char
, unsigned short int
, unsigned int
, unsigned long int
, ve unsigned long long int
, bunların her biri aynı miktarda depolama alanını kaplar ve tip tamsayıdır imza karşılık gelen aynı hizalama gereksinimleri vardır "
Genel olarak, farklı platformlarda derlediğinizde sizeof (hemen hemen her şey) değişecektir. 32 bit platformda, işaretçiler her zaman aynı boyuttadır. Diğer platformlarda (64 bit açık bir örnektir) bu değişebilir.
Hayır, işaretçinin boyutu mimariye bağlı olarak değişebilir. Çok sayıda istisna vardır.
İşaretçi ve int boyutu, Windows 32 bit makinedeki Turbo C derleyicisinde 2 bayttır.
Böylece işaretçinin boyutu derleyiciye özgüdür. Ancak genellikle derleyicilerin çoğu 32 bitte 4 bayt işaretçi değişkenini ve 64 bit makinede 8 bayt işaretçi değişkenini desteklemek için uygulanır).
Dolayısıyla, işaretçinin boyutu tüm makinelerde aynı değildir.
İşaretçinizin boyutunun 4 bayt olmasının nedeni, 32 bit mimari için derlemenizdir. FryGuy'un işaret ettiği gibi, 64 bit bir mimaride 8 görürsünüz.
In Win64 (Cygwin GCC 5.4) , en örnek aşağıda görelim:
İlk olarak, aşağıdaki yapıyı test edin:
struct list_node{
int a;
list_node* prev;
list_node* next;
};
struct test_struc{
char a, b;
};
Test kodu aşağıdadır:
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;
Çıktı aşağıdadır:
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
Bunu 64 bit sizeof(pointer)
olarak görebilirsiniz 8
.
İşaretçi, bir adres için yalnızca bir kaptır. 32 bitlik bir makinede, adres aralığınız 32 bittir, bu nedenle bir işaretçi her zaman 4 bayt olacaktır. 64 bitlik bir makinede 64 bitlik bir adres aralığınız vardı, bir işaretçi 8 bayt olacaktır.
Tamlık ve tarihi ilgi için, 64bit dünyasında, esas olarak Unix tipi sistemler ve Windows arasında LLP64 ve LP64 adlı uzun ve uzun uzun tiplerin boyutları üzerinde farklı platform sözleşmeleri vardı. ILP64 adında eski bir standart da int = 64-bit genişliğinde olmuştur.
Microsoft, LLP64'ü uzun uzunluk = 64 bit genişlikte, ancak uzun süre 32'de kaldı, daha kolay taşıma için.
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