KISA ÖZET
(ki ben de en üste koyacağım):
(0) İşaretçilerin adres olarak düşünülmesi genellikle iyi bir öğrenme aracıdır ve genellikle sıradan veri türlerine işaretçiler için gerçek bir uygulamadır.
(1) Ancak, çoğu, belki de çoğu, işlevlere yönelik işaretçiler adres değildir, ancak bir adresten daha büyüktür (genellikle 2x, bazen daha fazla) veya aslında işlev ve benzeri adresleri içeren bellekteki bir yapıya işaretçilerdir. sabit bir havuz.
(2) Veri üyelerine ve yöntemlere işaretçiler genellikle daha da yabancıdır.
(3) FAR ve YAKIN işaretçi sorunları olan eski x86 kodu
(4) Güvenli "yağ işaretçileri" olan birçok örnek, özellikle IBM AS / 400.
Eminim daha fazlasını bulabilirsin.
DETAY:
UMMPPHHH !!!!! Şimdiye kadar cevapların çoğu oldukça tipik "programcı weenie" cevapları - ama derleyici weenie veya donanım weenie değil. Bir donanım weenie gibi davrandığım ve genellikle derleyici weenies ile çalıştığım için, iki sentimi atayım:
Pek çok, muhtemelen çoğu, C derleyicilerinde, türdeki verilere bir işaretçi T
aslında adresidir T
.
İnce.
Ancak, bu derleyicilerin çoğunda bile, belirli işaretçiler adres DEĞİLDİR. Bunu bakarak anlatabilirsiniz sizeof(ThePointer)
.
Örneğin, işlevlere yönelik işaretçiler bazen sıradan adreslerden çok daha büyüktür. Veya bir miktar dolaylılık içerebilirler. Bu makaleIntel Itanium işlemcisini içeren bir açıklama sağlar, ancak başkalarını gördüm. Tipik olarak, bir fonksiyonu çağırmak için sadece fonksiyon kodunun adresini değil, aynı zamanda fonksiyonun sabit havuzunun adresini de bilmelisiniz - sabitleyicilerin oluşturmak zorunda olduğu derleyiciden ziyade sabitlerin tek bir yükleme talimatı ile yüklendiği bir bellek bölgesi Çeşitli Yük Anında ve Üst Karakter ve OR komutlarında 64 bit sabit. Yani, tek bir 64 bit adres yerine 2 64 bit adrese ihtiyacınız var. Bazı ABI'ler (Uygulama İkili Arabirimleri) bunu 128 bit olarak hareket ettirirken, diğerleri işaretçi aslında bir dolaylılık düzeyi kullanır, işlev işaretçisi aslında belirtilen 2 gerçek adresi içeren bir işlev tanımlayıcısının adresidir. Hangisi daha iyi? Bakış açınıza bağlıdır: performans, kod boyutu, ve bazı uyumluluk sorunları - kod genellikle bir işaretçinin uzun veya uzun bir uzunluğa dönüştürülebileceğini varsayar, ancak uzun uzunluğun tam olarak 64 bit olduğunu varsayabilir. Bu tür kodlar standartlara uygun olmayabilir, ancak yine de müşteriler bu kodun çalışmasını isteyebilir.
Birçoğumuz YAKIN POINTER ve FAR POINTERS ile eski Intel x86 segmentli mimarinin acı dolu anılarına sahibiz. Neyse ki bunlar şu ana kadar neredeyse tükenmiş durumda, bu yüzden sadece hızlı bir özet: 16 bit gerçek modda, gerçek doğrusal adres
LinearAddress = SegmentRegister[SegNum].base << 4 + Offset
Korunmuş moddayken,
LinearAddress = SegmentRegister[SegNum].base + offset
sonuçta ortaya çıkan adres, segmentte belirlenen bir sınıra göre kontrol edilir. Bazı programlar gerçekten standart C / C ++ FAR ve YAKIN işaretçi bildirimleri kullanmamıştır, ancak birçoğu sadece *T
--- derleyici ve bağlayıcı anahtarları olduğunu söyledi, örneğin, kod işaretçileri işaretçilerin yakınında olabilir, her şeye karşı sadece 32 bit ofset olabilir CS (Kod Segmenti) kaydı, veri işaretçileri 48 bit değer için hem 16 bit segment numarası hem de 32 bit ofset belirterek FAR işaretçileri olabilir. Şimdi, bu miktarların her ikisi de kesinlikle adresle ilişkilidir, ancak aynı boyutta olmadıklarından hangisi adresdir? Ayrıca, segmentler, gerçek adresle ilgili öğelere ek olarak, salt okunur, okuma-yazma, yürütülebilir - izinler de taşıdı.
Daha ilginç bir örnek olan IMHO, IBM AS / 400 ailesidir (veya belki de öyleydi). Bu bilgisayar, C ++ 'da işletim sistemi uygulayan ilk bilgisayarlardan biriydi. Bu makinedeki işaretçiler tipik olarak gerçek adres boyutunun 2 katı idi - ör. bu sunumda128 bit işaretçiler, ancak gerçek adresler 48-64 bit ve yine, okuma, yazma gibi izinlerin yanı sıra arabellek taşmasını önleme sınırı sağlayan bazı ekstra bilgilerdi. Evet: bunu C / C ++ ile uyumlu bir şekilde yapabilirsiniz - ve eğer her yerde bu olsaydı, Çin PLA'sı ve Slav mafyası pek çok Batı bilgisayar sistemine girmeyecekti. Ancak tarihsel olarak çoğu C / C ++ programlaması performans güvenliğini ihmal etmiştir. En ilginç olanı, AS400 ailesi işletim sisteminin, ayrıcalıksız koda verilebilen, ancak ayrıcalıklı olmayan kodun sahte veya kurcalanamadığı güvenli işaretçiler oluşturmasına izin verdi. Yine, güvenlik ve standartlarla uyumlu olsa da, standartlarla uyumlu çok özensiz C / C ++ kodu böyle güvenli bir sistemde çalışmaz. Yine resmi standartlar var,
Şimdi, güvenlik sabun kutumdan çıkacağım ve işaretçilerin (çeşitli türlerde) genellikle gerçekte adres olmadığı başka yollardan bahsedeceğim: Veri üyelerine işaretçiler, üye işlev yöntemlerine işaretçiler ve bunların statik sürümleri bir sıradan adres. Gibi bu yayını diyor ki:
Bunu çözmenin birçok yolu vardır [tekli ve çoklu miras ve sanal miras ile ilgili problemler]. Visual Studio derleyicisi bununla başa çıkmak için nasıl karar verir: Çok miras alınan bir sınıfın üye işlevine bir işaretçi gerçekten bir yapıdır. "Ve" Bir işlev işaretçisi döküm boyutunu değiştirebilir! "
Muhtemelen (in) güvenlik konusundaki benim tahminimden tahmin edebileceğiniz gibi, bir işaretçinin ham adres yerine bir yetenek gibi ele alındığı C / C ++ donanım / yazılım projelerinde yer aldım.
Devam edebilirdim, ama umarım bu fikri anlarsın.
KISA ÖZET
(ki ben de en üste koyacağım):
(0) işaretçilerin adres olarak düşünülmesi genellikle iyi bir öğrenme aracıdır ve genellikle sıradan veri türlerine işaretçiler için gerçek bir uygulamadır.
(1) Ancak, çoğu, belki de çoğu, işlevlere yönelik işaretçiler adres değildir, ancak bir adresten daha büyüktür (genellikle 2X, bazen daha fazla) veya aslında işlev ve benzeri adresleri içeren bellekteki bir yapıya işaretçilerdir. sabit bir havuz.
(2) Veri üyelerine ve yöntemlere işaretçiler genellikle daha da yabancıdır.
(3) FAR ve YAKIN işaretçi sorunları olan eski x86 kodu
(4) Güvenli "yağ işaretçileri" olan birçok örnek, özellikle IBM AS / 400.
Eminim daha fazlasını bulabilirsin.