İşaretçiler için iyi bir açıklama nedir? [kapalı]


72

Kendi çalışmalarınızda (kendi başınıza veya bir sınıf için) sonunda, gerçekten işaretçileri anladığınızda bir "ah ha" anınız oldu mu? Özellikle etkili görünen yeni başlayan programcılar için kullandığınız bir açıklamanız var mı?

Örneğin, yeni başlayanlar ilk önce C ile işaretçilerle karşılaştığında, derlenene kadar sadece &s ve *s ekleyebilirler (bir zamanlar benim yaptığım gibi). Belki de işaretçilere sizin veya öğrenciniz için "tıklama" yapan bir resim veya gerçekten iyi motive olmuş bir örnekti. Bu neydi ve daha önce işe yaramadı ki ne denedin? Herhangi bir konu önkoşul mu (örneğin yapılar veya diziler) oldu mu?

Başka bir deyişle, &s nin anlamını anlamak için neleri ve *bunları güvenle ne zaman kullanabilmeniz gerekiyordu? Sözdizimi ve terminolojiyi veya kullanım durumlarını öğrenmek yeterli değildir, bir noktada fikrin içselleştirilmesi gerekir.


Güncelleme: Şimdiye kadar cevapları gerçekten seviyorum; lütfen gelmelerini sağlayın. Burada birçok büyük bakış açısı var, ancak kavramın içselleştirilmesinden sonra birçoğumuzun kendimiz için iyi açıklamalar / sloganlar olduğunu düşünüyorum . Size doğduğunda detaylı bağlamlar ve koşullar arıyorum.

Örneğin:

Ben sadece işaretçilerden C'de sözdizimsel olarak anladım. Bir arkadaşımdan işaretçilere açıklama yapan iki arkadaşımın neden structbir işaretçi ile geçtiğini sordum . İlk arkadaş nasıl referans alması ve değiştirilmesi gerektiğinden bahsetti, ancak diğer arkadaşımın bana vurduğu kısa bir yorumdu: "Aynı zamanda daha verimli." 16 bayt yerine 4 bayt geçmek, ihtiyacım olan son kavramsal değişiklikti.


16
'Av tüfeği' yöntemi: çalışıncaya kadar her yere * s atın.
Michael K,

15
@Michael: Evet, sana bol şans.
Robert Harvey,

8
Bu soru, SO'da her dönem başında kısa bir süre sonra ortaya çıkıyor. En son enkarnasyon burada: stackoverflow.com/questions/4118647/…
Tim Post

10
İşaretçiler için iyi bir açıklama nedir? Brian Kernhigan ve Dennis Ritchie yazılım mühendislerinden nefret ediyor.
Adam Crossland

3
Hata ayıklayıcıda tek adımlı makine kodunu bir süre geçirdikten sonra benim için "tıklandı". Evet, bilgisayar mimarisinin temellerini biliyordum - Commodore 64'teki montajı öğrendim ve bundan sonra x86 ASM oldukça kolaydı. Bu yüzden zaten bir "adres" kavramını biliyordum, sadece C'nin sözdizimsel yapılarına nasıl eşlendiğini anlamadım.
zvrba

Yanıtlar:


25

Izgara Olarak Bellek Diyagramı

Genelde yaptığım şey, belleği bir "ızgara" olarak temsil etmektir, böylece adresleri oluşturabilir, farklı bellek alanlarını vurgulayabilir ve hücre değerlerine yazabilirim (veya dahası, ikili gösterimlerini) ve bellekteki işaretçileri değerlerine bağlayabilirim. işaret etmek. (Ve sonra hala bunun bir sadeleştirme olduğunu belirtiniz).

Genelde öğrencilerimin çoğu için bir "ohhhh" anıdır.

Sembol hokkabazlık

Öyleyse, nasıl kullanılacağını unutmayı bırakmalarına gelince & ve *, çok basit: matematik veya fizik hesaplamalarını yaptıkları gibi sunma. Mesafeyi saatte km cinsinden ayırırsanız km / sa hıza ulaşırsınız. Neyin dışarıda olması gerekiyor? Basit.

kurtarmaya printf

Bunlarla anlattığınız şeyi görsel olarak temsil eden sadece birkaç temel örnek vermek, onları anladıklarını düşündüklerinde rahatlatacak ya da "ah, bunu anlamadım" deme fırsatını verecektir.

Kapsamlı Olun

Basit türler için işaretçileri örtün ve adresleme ile veri türünün boyutu arasındaki farkları, daha sonra yapıları, sonra dizileri ve çoklu seviyeleri anladığından emin olun.

Ardından işaretçi aritmetiğini başlatın.


Zeyilname: Özyineleme

Genel olarak, özyinelemeyi benzer şekilde görsel bir sunum kullanarak açıklarım. Tek bir karakter yazan önceden yapılmış bir işlevi kullanarak alfabeyi yazdırmalarını isteyin ve ardından sadece iki satırı değiştirerek ters sırada yazdırmalarını isteyin.

Genellikle bir "ne ...?" Var. moment ve sayısal değerleri yazdırmak ve adımları girintiye almak için printf'e başka bir parametre eklediğinizde, rahat bir nefes alır.


Alternatifler: Play-Doh Modeli ve Su Bardakları

Aslında üniversitedeki bazı meslektaşlarım öğrencilere oyun hamuru pastasını kullanarak göstericileri ve hafızaya girişleri açıklayan bir video gösteren. Programlamayı kavramakla ilgilenen çok genç öğrenciler dışında (ama genellikle onları çok erken bir işaretçi kullanarak bir dile yönlendirmeyeceğim olanlar) haricinde, bu tekniği kendim gerçekten kullanmamıştım. Temel olarak hafıza alanlarını temsil eden diğer büyük oyun hamuru toplarına ekleyebileceğiniz ve bunları birbirine bağlamak için (bağlantılı bir veri yapısında olduğu gibi) bir araya getirebileceğiniz ya da bir araya getirebileceğiniz küçük bir oyun hamuru toplarını kullanmak (bitişikteki gibi) hafıza alanı). İşaretlenen bellek alanları için farklı renkler kullanmak ve işaretçiler de yardımcı olur. Ama hala bir Izgara Olarak Bellek olayının daha iyi çalıştığını düşünüyorum. açıkça işaret edebileceğiniz gibi, işaretin gerçekten bir "harita / ızgara" da olduğu gibi "adresleme" meselesi olduğunu. Oysaki Play-doh modu hala her şeyin bellekte birbirleriyle gerçekten "temas ettiğini" düşünmekle karıştırıyor.

Su Bardağı olayı doğrudan bir meslektaşım tarafından da kullanılıyordu, fakat onun ortaya çıkıp çıkmadığını bilmiyorum. İlginç bir yaklaşımdı, ancak birçok öğrencinin açıklamadan şaşkın kaldığını fark ettim. DevSolo'nun Kahve Fincanı tekniğine benzer bir şey . Ama bence öğrencileri kapları, veri yapılarını, işaretçileri ve dizileri birbirine karıştırmak gibi yanıltıcı bir durum. Sanırım başlangıçta dizileri açıklamak ilginç bir yaklaşım olabilir, ama çok uzun süre buna bağlı kalmam.


Vay, ödül için teşekkürler. Cevabın takdir edilmesine sevindim.
haylem

Çıkarın: | Bu bazı iyi öğretim gibi geliyor!
Spooks

80

Bir zamanlar söylediğimden daha bilge biri:

Rahibe Wu Jincang, Altıncı Patri Huineng'e “Ben yıllardır Mahaparinirvana sutra'sunu çalıştım, ancak tam olarak anlamadığım birçok alan var. Lütfen beni aydınlatın” dedi.

Patrik, "Ben okuma yazma bilmiyorum. Lütfen bana karakterleri oku ve belki de anlamını açıklayabilirim" diye cevap verdi.

Rahibe, “Karakterleri bile tanıyamıyorsunuz. Anlamını nasıl anlayabilirsiniz?” Dedi.

“Hakikatin kelimelerle ilgisi yok. Hakikat gökyüzündeki parlak aya benzetilebilir. Bu durumda, kelimeler bir parmağa benzetilebilir. Parmak, ayın yerini gösterebilir. Ancak, parmak o değildir. aya bakmak için parmağın ötesine bakmak gerekir, değil mi? "


13
Ay'ı serbest bırakmak için +1. Yapabilseydim, koan için +1.
Tim Post

14
Bir parmağın yukarı sesinin sesi nedir?
Adam Crossland

3
@Adam, bir fare veya bir trackpad kullanmanıza bağlı olarak değişir.
Daniel Joseph,

7
@Frank BÜYÜK bir teklif oldu. Yine de bu fikri kavramaya yardımcı olmayacağını düşünüyorum. Özellikle işaretçilere yeni gelen biri için.
Gulshan

11
Bu güzel bir hikaye ... ama işaretçileri iyi açıklamaktan ziyade insanların bu yüzden oy kullandıklarından şüpheleniyorum.
Kyralessa

46

Diyagramların çok yardımcı olduğunu gördüm. Örnek:

işaretçi diyagramı


Bu tür bir diyagram, işaretçilerin kendi değişkenleri olduğunu görmeme yardımcı oldu, ancak başka bir nesnenin, yani dizenin veya dizenin yeri olan bir değer içeriyordu. Ayrıca, kalemle yapıldığında, programımı kağıt üzerinde veya kara tahta / beyaz tahta üzerinde izlemek için kullanabilirim.


4
"İşaretçi" içindeki değer 4 olmalı ya da dizi indeksleri (veya hafıza adresleri) 0'dan başlamalıdır. Aksi takdirde, 3 değerini tutan bir işaretçi konum 4'e nasıl işaret edebilir?
MAK

++ Bu tam olarak açıklayacağım şeydi. Fortran'da başladım (daha iyisi ya da kötüsü için!). Fortran'da, o zamanlar yapı dizileri yerine paralel diziler kullandık ( yeni bir şey değil ). Bir dizi dizilerde "başka bir satır" dizini içeriyorsa, onu "işaretçi" olarak adlandırdık ve bu heyecan vericiydi. Bağlantılı listeler yaptık, ağaçlar, siz adlandırın.
Mike Dunlavey

2
Nerede depolandığını gösteren resimler kullanılarak ve işaretçilerin nereye işaret ettiğini göstermek için oklar kullanılarak en iyi açıklanmış işaretçiler bulunur.
gablin

32

İşaretçiler hakkında ilk "öğrendiğimde", buna güveniyordum. Üniversitem karar vermeyi çok uzun zaman önce Java etrafındaki müfredata odaklanmadan önce vermişti, bu yüzden Veri Yapılarım profesörü C hakkında bir ders verdi ve bir şeye giriyormuş gibi hissettiğim bir işaretçi içeren bir XOR-Listesini uygulamamızı istedi. yolu kafamda.

Tanımı anladım:

İşaretçi, bir değişkenin adresini içeren bir değişkendir

Ama yine de kavramın büyük bir bölümünü anlamadım. Geriye baktığımda, üç şeye odaklandığını düşünüyorum:

  1. Tam olarak ne olduğunu bir bellek konumu? (O sırada bir Bilgisayar Organizasyonu dersi almadım)

  2. Garip bir sözdizimi (Öyleyse neden "int * ip" gibi tam olarak tanımlanıyor ama daha sonra "ip" olarak değişkene başvuruyorum?)

  3. Bir değişkenin adresini sadece değişkeni kullanmak yerine saklamak ne kadar faydalıdır?

K & R kitabını satın alıp, işaretçiler için gerçekten bir kavrama sahip olduğum her sorunu çözene kadar değildi. Bilgisayar Organizasyon sınıfını (C öğrenmeden önce gerekli olması gerektiğini düşünüyorum) uzun zamandır tamamlamış olmama rağmen, bir kısmı işaretçilerin işlevler, diziler, yapılar için kullanılabileceğini fark etmem gerekiyordu. faydalı şeyler yapmak ve sadece sıradan değişkenlerin adresleri için depolama yapmak değildir.

Ama benim "aha" anım, K&R'nin basit bir işaretçi tanımlamanın tuhaf sözdizimini açıklamasının yoluydu. Kitap boyunca not aldım (anlamayı ilerletmek için kitabın yazdığı noktaları kendi sözlerime aktardım) ve bununla ilgili olanı:

İşaretçi, bir değişkene adres içeren bir değişkendir. Bir işaretçi '*' işleci ile hem tanımlanır hem de giderilir (işaret ettiği hafıza konumunda saklanan değeri verir); ifade anımsatıcıdır.

Ex.: 
   int a;      /* Variable 'a' is an integer */

   int *ip;   /* Variable ip is a pointer and dereferencing it gives an integer.
                 In other words, the expression *ip is an int, so ip is a pointer
                 to an int */

Kafamda çok basit bir şey var olana kadar işaretçilerin daha gelişmiş kavramlarını tam olarak kavrayamadığımı her zaman hissettim. Bu görevden sonra beni çok rahatsız etmişti (bu arada çok iyi yapmadım; bu arada) neden "* ip" in (* düşündüğüm) "* ip" i tanımladıktan hemen sonra yoktu. Bunun üstesinden gelmek, işlev göstericileri ve daha karmaşık tanımları gibi işaretçileri içeren daha gelişmiş kavramlar için önemlidir:

char (*(x())[])()

Sonuçta, ben işaretçiler kavramının gerektirir:

  1. Bilgisayarda hafızanın nasıl düzenlendiğine (ve hafızanın ne olduğuna) temel bir anlayış.

  2. İşaretçilerin ne kadar güçlü olabileceği bilgisi (gerçek dünya kullanımı, sadece öğrenme amacıyla öğrendikleri soyut bir kavram değil).

  3. Hiyerogliflerin halk arasında "işaretçi tanımı" olarak bilinen şifresini çözmek

Sonuç olarak, işaretçiler hakkında bilgi edinirken en az 3 "aha" anının olması gerektiğini düşünüyorum. Ben hala bir öğrenciyim, bu yüzden kavramı öğrenmekte hala taze olan birinin bakış açısını takdir edersiniz.


3 "Ah ha!" İçin +1 monents. Groking işaretçiler katmanlar halinde gelir. Noktaları işaretçilere sadece yaklaşık yarım anladığımı fark etmeden önce uzun bir süre "noktaları anladım" :)
Binary Worrier

'İşaretçileri anlamayan'ın çok büyük bir bölümünün aslında garip C sözdizimi üzerinde tetik oluşturması konusunda tamamen haklısınız. [Düşünüyor: Bu tür bir sözdizimiylePointerTo<int> a
kırmanın

Anlaştım, @ Benjol. Sözdiziminin int* ipdaha yaygın olmamasına şaşırdım . Sonunda böyle biçimlendirilmiş kodu görünce işaretçileri anlamaya başladım. Sonra "ip pointer int türünde" olarak okuyabilirim.
Jacob

19

İşaretçi, masaüstünüzdeki uygulama kısayollarına benzer. Kısayolu silin ve hedef hala mevcut. Kısayolu başlattığınızda hedef başlar.

Bunun çalışmasını her zaman masaüstümde bir txt dosyası oluşturarak ve dosyaya iki kısayol yaparak açıklarım. Kısayolları kopyalayıp sildikten sonra, insanların 'referansların' arkasındaki fikri anladıklarını görebilirsiniz.

Grup kısayolların arkasındaki temeli anladıktan sonra, istediğiniz şekilde işaretçileri açıklamaya başlayabilirsiniz. Muhtemelen kolayca anlayacaklardır.


Bu kötü bir benzetme değil. Kelimenin tam anlamıyla bir "hard-link" alan herkes için eklemek için sadece birkaç nokta, dizinleri değiştirse bile her zaman hedefine işaret edecek, nesne değiştirilmiş olsa bile bir işaretçi orijinal belleğe işaret edecektir. Bir "hard-link" size hedefin artık var olmadığını, bir sarkıcı işaretçi göstergesinin NULL olarak ayarlanması gerektiğini söyleyecektir.
snmcdonald

Sabit bağlantı, referans sayılan akıllı işaretçi gibidir
jk.

1
+1. İşaretçileri açıklamak için en iyi pratik analojilerden biri. Öğrencilerin hemen fikri anlayacağından eminim, çünkü bu işlevsellik herkes tarafından en çok kullanılanıdır.
Karthik Sreenivasan

13

8-10 yıl önce, bir topluluk kolejinde bir int "C" kursu verdim. Bu her zaman keşfetmek için eğlenceli bir konuydu. En iyi sonuç veren, iş arkadaşınızla birkaç kez konuştuktan sonra bir fincan kahve ve elinizi kullanmaktı.

Bir kahve fincanının (veya diziler için sıralarının) benzetmesini değişken olarak kullandım (bir şeyi tutabilir). Daha sonra bir şey tutabilecek elimi kullandım ya da işaret parmağımı bir kahve fincanına "yönlendirerek" uzatarak.

Yakın bir el boştu, kafamı gösteren bir parmak (sahte bir tabanca gibi) sarkan bir işaretti.

Daha sonra birkaç gösteri ve hata ayıklayıcıyı gezdirerek çoğunu tıkladı.


3
Kafamı karıştırdın zaten.
kirk.burleson

1
@Kirk, nasıl yani? bir bakayım, temizleyebilir miyim?
DevSolo

4
++ Sana bu şeyleri düşündürecek öğretmek gibisi yok.
Mike Dunlavey,

Üniversitedeki öğretim görevlilerimden biri, kahve fincanı yerine (bir tanesi "gülmek için" Niel "olan) öğrencileri kullanarak benzer bir şey yaptı. İzleyiciye el sallayarak işaret etmek sarkan bir işaretti, çünkü herhangi bir şeye işaret ediyor olabilirdi.
Kaz Ejderha,

2
Sallanan bir işaretçi Neil'i işaret etmek, daha sonra işaret ettiği yeri değiştirmeden sandalyesini terk etmesini sağlamak gibidir ... sonra o işaretleyiciyi takip etmeye çalışmak ve orada ne olduğuna bakılmaksızın orada ne bulduğunu yorumlamak.
Jon Purdy

10

"İşaretçileri nasıl kavradı" sorusunu duyduğumda gerçekten endişelendim. Her zaman kavramın inanılmaz derecede basit olduğunu ve programcılara büyük güç sağlayan dillerin mantıklı bir evrimini düşündüm.

Beni endişelendiren şey, işaretçiler kavramını anlamakta hiç zor olmadığım. Bu yüzden ne zaman burada "nihayet ne zaman aldın" diye tekrar tekrar, düşünmeye başlarsın:

Gerçekten anladın mı? Belki de hiç yapmadım?

Belki de bu konseptin aldatıcı görünmesinin nedeni, kendisiyle henüz karşılaşamayan herkese, işaretçilerin zor olduğunu ve bunun için öğrenebileceğiniz yüzlerce yol olduğunu söylememizdir.

Bu fikri oraya fırlatıp atıyorum, elbette şahsen iyi bir şemayı severim ve Steve Gibson her zaman bir şeyi açıklamak için harika bir iş çıkarır !


İlginç ... o zaman hangi dili kullandınız? C sözdiziminin bir çok insanı etkilediğini düşünüyorum. İlk önce montajı biliyor olsaydın, bunun bir nedeni olduğunu görebiliyordum. [BTW, buna oy vermek istiyorum, ancak bugünlük
sınırıma

İlginçtir ki, Python'da (ve University of Java'da) uzun süredir "tehlikeli" işaretçiler hakkında hiçbir bilgim yoktu. Sonra C ++ 'ı tercih ettiği dil olarak kullanan ve doğrudan oradaki güvercin olan "nesne yönelimli yöntemler" modülünü kullandım.
Marcus Whybrow

Ayrıca, bir programın bellekte nasıl temsil edildiğine dair bir anlayışa sahip olmak kesinlikle yardımcı olabilir, ancak işaretçilerin bir dile neden faydalı bir katkı olduğunu anlamayı tercih ederim, çünkü siz de aynı şeyi yapıyorsunuz. orijinal tasarımcılar olarak süreç.
Marcus Whybrow

+1 İnsanların işaretçilerin neden zor ya da gizemli olduğunu düşündüğünü bilmiyorum.
ggambett

Evet, işaretçiler her zaman açıkça o kadar basit ve kullanışlıdır ki, onlar hakkında "zor" bir şey olduğunu düşünemiyorum. Herhangi bir kursun öğretmeni "şimdi, bu biraz zor" derken nefret ediyorum, çünkü sadece çok yıkıcı. Sadece lanet olası şeyleri öğretin ve öğrencilerin zor olduğunu düşündükleri gibi kendileri için karar vermelerini sağlayın.
Jon Purdy

7

Hiçbir zaman C'deki işaretçilerle ilgili bir sorunum olmadı, ama bunun nedeni ilk önce assembler'ı öğrenmek zorunda olmam olabilir. Artık adresleri kendim yönetmek zorunda kalmamak bir rahatlama oldu. Bu yüzden belki de cevap (bunun öğrettiğiniz bir şey olduğunu varsayarsak) öğrencilere birlikte çalışabilecekleri öykünmüş bir dil vermektir. Bunlar olacak daha sofistike bir şey yazma sürecinde onu anlamaya "Merhaba dünya."


Bir analoji kullanmaya çalışmak yerine, daha ilkel bir soyutlamayı uyarlamak için + 1.
Anonim Tip

Lisemde , tahtaya hiç dokunmadan ya da gerçek bir bilgisayara dahil olmadan öğretilebilecek bir kibrit kutusu bilgisayarını incelemek için bir birim Bilgisayar Etütleri verildi .
rwong

@Larry Coleman, Assembly !!!!!!!!!!! Önce C den önce denemek istiyorum. Lütfen nerede öğrenmeye başlayacağımı söyle. Ücretsiz Ebooks, Ücretsiz PDF? IDE? Lütfen!!!!!!!!!!!!!!!!!!!
Spacez Ly Wang,

7

İşaretçi, değeri başka bir değişkenin hafıza adresi olan bir değişkendir.


Zarif, neden daha karmaşık hale getirdin?
Bjarke Freund-Hansen,

İşaretçiler hemen sezgisel ve kullanışlı görünmüyorsa, yanlış açıklanmıştır.
Jon Purdy

6

İşaretçileri nasıl öğrendim? Basit bir derleyici birinci sınıf koleji yazarak.

İşaretçileri layman açısından nasıl açıklayabilirim? Dizin kartlarında depolanan bir kütüphane kataloğunun (tarihli mi? Her kart ("işaretçi"), bir kitabın ("veri") bulunduğu yer hakkında bilgiler içerir, ancak aslında kitabın kendisini içermez. Kartı değiştirirseniz ("işaretçi aritmetik"), tek yaptığı, kitabın işaret ettiği kitabı değiştirir ve kitabın üzerinde bir etkisi olmaz - sadece adresi mahvetmemeye dikkat edin, yoksa var olmayan bir kitabı işaret edebilirsiniz. hatta yanlış kütüphane bile. Bununla birlikte, karttaki "adresi" izler ve kütüphanenin uygun bir bölümüne ("işaretçiyi kaldır") giderseniz, kitabın kendisini görebilir / değiştirebilirsiniz.


Tam olarak bu açıklamaya sahip olduğum CS kursumun hafızası için +1
Gary Rowe 21

Bir bakıma iyi, fakat kartlar kitabın nerede olduğunu söylemediğinden biraz yanıltıcı . Hala spor ayakkabı odaklı bir arama algoritması uygulamanız gerekiyor. Belki bu daha iyi bir veritabanını modellemektedir - saklanan bir nesneye bir anahtarla (çağrı numarası) atıfta bulunulur.
DarenW

+1 Analoji, Barfieldmv tarafından açıklanan konseptle aynı ancak daha gerçek bir yaşam yaklaşımı ile korunuyor .
Karthik Sreenivasan

5

İşaretçileri öğrenecek birinin normal değişkenlerin ne olduğunu ve C'de nasıl çalıştıklarını bildiğini varsayacağım. Şimdi, işaretçileri bazı özellikleriyle tanımlamaya çalışalım.

  • Onlar da değişkenlerdir, fakat farklı niteliktedirler. Değişken alanda iki katman olduğunu varsayalım. Farklı tipteki normal değişkenler üst katmanda, alt kattaki işaretçilerde bulunur. Bu rakam gibi-

    alt metin

  • 'Pointer' adından da anlaşılacağı gibi, işaretçiler bir şeylere NOKTA yapabilir. Parmağımızın bir nesneyi gösterebileceği gibi. İşaret ettikleri şeyler neler? Bunlar normal değişkenler. Kısacası, "İşaretçiler normal değişkenlere işaret eder".

  • Normal değişkenler gibi, işaretçiler de int, char veya float gibi aynı sayıda türdedir. Ve belirli bir tipteki bir işaretçi sadece aynı tipteki değişkenleri gösterebilir.
  • Bir işaretçi bir değişkeni işaret edebilir ve daha sonra aynı işaretçi başka bir değişkeni işaret edebilir. Sadece tip aynı olmalı. Bu nedenle, işaretçinin bazı değişkenlerle ilişkisi kalıcı değildir ve değiştirilebilir.
  • Peki, bir işaretçi nasıl ilan edilir? Neredeyse normal değişkenler gibi. Addan önce bir yıldız işareti ( *) basmanız gerekir . Sevmek-

    int *pointer;
    
  • O zaman, bir işaretçi bir değişkenle nasıl ilişkilendirilir? &İşleci bu gibi değişkenlerden önce kullanma

    pointer = &variable;
    
  • Bir işaretçi bir değişkene işaret ederek nasıl kullanılır? Bu aynı zamanda, bir yıldız ( *) isminden önce de yapılır . Sonra şimdi işaret ettiği değişkenin yerine kullanılabilir.

    *pointer = var1 + var2;
    

    onun yerine

    variable = var1 + var2;
    
  • Şimdi bazı kodlarla işaretçilerle oynayın. Şimdi işaretçilerin bu özelliklerine alışın. Bu noktaya kadar, işaretçilerin yaptıklarından bahsediyoruz. Bir kez sorununuzu çözdükten sonra, işaretçilerin bazı değişkenleri nasıl gösterdiğini ve normal aritmetik işlemler uygulanırsa nasıl tepki verdiklerini inceleyin. Ardından işaretçilerle diziler ve işaretçiler arasındaki ilişkiyi işaretçilere yönlendirin.

İşaretçi öğrenmekle ilgili önereceğim tek şey bu.


"Önce ne yapar, sonra nasıl" işlemini takip etmek istedim. Soyutlama!
Gulshan

5

Sorunun gözden geçirilmiş gerekliliğini desteklemek için düzenlendi

"İşaretçi sonrası" anlayışına giden yolum (doğru hatırlıyorsam) böyle oldu. Hala bir BBC Micro ile takılmaya başladığım andan itibaren basit bir programlama programı deneyimi yaşadım, bu yüzden bir demet kutu olarak hafıza kavramına sahip oldum (bunun için aşağıya bakınız). Bu, dizilerin kullanılmasıyla güçlendirildi. Ancak, C dünyasına giriyordum ve iplerle uğraşmak zorunda kaldım ve bu da işaretçiler anlamına geliyordu. BASIC’de bu önemsizdi, montajcıda onlarla çalışmak zorunda kalmamıştım ve şimdi klasik C’de hepsi işaretçiler ve şeyler. Ah, ama şu şekilde (boş sonlandırılmış) dizeleri olan dizilere geri dönebilirim:

char s[] = "Hello, world!";
printf("%s",s);

Her şey yolunda ve güzel, bu sadece sonunda bittiği yeri göstermek için sonunda sıfır karakterli bir karakter dizisidir (küçük dünyamda karakter başına 8 bit). Printf sadece bu diziyi alır ve üzerine basar. Peki ya bu dizgiyi bir işleve geçirmek istersem?

void print_str(char* p) {
  printf("%s",p);
}

Kılavuz ne diyor, peki bu ne *? Hmm, char * "char'a işaretçi" anlamına gelir. Tamam ... beni kaybettim. Ardından char * 'ın p [0]' a eşdeğer hale gelmesi bana şafak verdi. Tamam, bunu kullanabilirim, ancak işaretçilerin neler olduğunu hala bilmiyordum. Yani, bunlardan biriyle bazı verileri nasıl ayarlarım? Yine el kitabına ...

char* p = "Hello World!";

Yukarıdakileri yazarken kendime "bir karaktere bir işaretçi koy ve bu karakter dizisine eşit ayarla" diyorum. Her nasılsa, bu işaretçi bir dizi ihtiyacını ortadan kaldırıyor. Sanırım derleyici benim için bir şeyler yapmak için bazı şeyler yapıyor. Peki bu göstergeyle diziyi nasıl değiştirebilirim? Dizi sürümünü kullanabileceğimi biliyorum

 s[2] = 'L'; 

peki "pointer speak" içindeki eşdeğer nedir? Yine bu el kitabına ...

*(p+2) = 'L';

Ben * basitçe "bellek adresinin içeriği" anlamına ve varsayalım (p+2)olduğunu s[2]. Bunun anlamı p işaretçisi ... sadece ... bir ... adres ... bong!

Aydınlanma sesi var. Birden bire işaretçilere daldım (uzun zaman önceydi, eski zamanlayıcılar daha sonra "grok" yapmadık). Sadece dolaylıydı.


Orijinal:

Tamam, benim 2c değerim:

Bir hafızanın bir demet olduğunu hayal edin. Her kutunun yanında bir numara vardır (adres). Her kutu bir numara içerir (içerik). 2 şekilde bu kutulara çalışabilirsiniz: değişkenler (Ben kutu N içeriğini istiyorum), işaretçiler (I kutusunun içeriğini istediğiniz kutu N olursa olsun ). İşaretçiler basitçe dolaylıdır.

Ve bilmeniz gereken her şeyi kapsayan büyük cevap için - bunu okuyun .


++ Bu konuya öğrettiğim yöntem az ya da çok.
Mike Dunlavey,

OP gereksinimlerini desteklemek için düzenlenmiş makale.
Gary Rowe

Dizelerinizin sonuna bu fazladan NUL karakteri ekleyen hangi kılavuzu kullanıyordunuz?
Rob Gilliam,

@raimesh Çok eski bir (1991 civarında). Hangisini hatırlayamıyorum.
Gary Rowe,

1991? Bu bir C dili kılavuzu için eski değil - K & R'nin ilk baskısı 1978'de yayınlandı! Sadece, dize sabitlerinin sonuna \ 0 koymanız gerektiğini öneren bir kılavuz olduğunu merak ettim. (Aslında, tekrar bakmak, demek istedin \ n?)
Rob Gilliam

4

Küçük tahta bloklar al.

bir ucuna metal kancalar, diğer ucuna metal gözler ekleyin.

Artık oynayabileceğiniz şeylerle bağlantılı bir liste yapabilirsiniz.

Bu fiziksel pervane ile açıklamayı deneyin. İlk yıl öğrencilerine işaretçi öğretirken bunu sık sık diledi.

Küçük metal kanca işaretçi, ahşap bloğun gösterdiği şeydir.

Ben bloklarla oynadıktan sonra kimseyi alamadım.


4

Tüm kabartmayı yeni kaldırdığımda ve işaretçiyi büyülü bir varlıktan ziyade herhangi bir değişken olarak görmeye başladığımda hayatımı kolaylaştırdım (çok uzun zaman önce 11. sınıfta) .. sadece 3 şeyi biliyorum:

  1. İşaretçi, başka bir değişkenin adresini (veya yalnızca herhangi bir adresi) depolayan bir değişkendir.
  2. *, işaretçi değişkeninde depolanan hafıza konumundaki değeri elde etmek için kullanılır.
  3. & operator bir hafıza konumunun adresini verir.

Gerisi, sözdizimsel şeker ve sağduyudur. Sadece bir kilitleme almak için işaretçileri kullanarak bazı basit C programlarını yazın (bağlantılı bir liste kitaplığı uygulamak gibi).


2
  1. İşaretçi, bir dizinin bir diziye genellemesi olarak düşünülebilir.
    • Büyük bir dizinin birkaç küçük, örtüşmeyen, değişken boyutlu diziye bölünebileceğini düşünün. Şimdi, bu küçük diziler genellikle dizi olarak düşündüklerimizdir. En büyüğü o zaman bilgisayarın tüm hafıza alanıdır. Küçük dizileri kesme işlemine bellek ayırma adı verilir.
  2. Bazı işaretçilerle birbirine bağlanmış bir dizi yapı, yönlendirilmiş bir grafik olarak düşünülebilir .
    • Her köşe bir değeri tutabilen bir değişkendir.
    • Bazı değişkenler işaretçilerdir ve her işaretçinin başka bir şeyde tam olarak bir çıkış kenarı olabilir.
    • İşaretçi olmayan değişkenlerin hiçbir çıkış kenarı yoktur. Herhangi bir sayıda gelen kenarı olabilir.

2

İşaretçilerimin etrafındaki koşulları tam olarak hatırlayamıyorum, ama bir c tarzı dizi hakkındaki düşüncelerimi hatırladım. (yani arr[3]aynı *(arr+3))

Bazı nedenlerden dolayı, bir işaretçi durumuna geldiğimde işaretçileri diziler olarak görmeyi çok faydalı buluyorum.


2

Temelde @Gary Rowe doğru modeli tanıttı. Üzerinde adresleri (sayıları) olan bir kutu seti olarak bellek. Her kutu bir değer (sayı) depolar.

Bir işaretçi fikri, bir kutudaki değeri başka bir kutunun adresi olarak yorumlamaktır. Bu değer, belirli bir kutuya atıfta bulunmak için kullanılır , bu nedenle referans olarak adlandırılır . Böylece çözümleyecek refere kutusu açma işlemidir.

eğer vbir değişken (kutu) ise, deyim

  • vdeğeri v, yani bana kutunun içinde ne olduğunu
  • *vdeğerinin dereference anlamına gelir v, yani bana değeri ile belirtilen kutuda ne verv
  • &vreferans anlamına gelir v, yani bana kutuyu yaz

İşaretçileri tamamen farklı bir şey olarak tanıtmanın amacına hizmet etmediğini düşünüyorum. Çocukken, benim için kavramak zor bir kavramdı. Her zaman gerçekten anlamadığım, birçok özel karaktere ihtiyaç duyan kara bir sihir gibi görünüyordu. İlk anladığımda, işaretçi aritmetik olmayan bir dilde çift dolaylı kullanarak küçük bir oyun yazarken oldu. Bu beni aydınlattı.

İşaretçiler bir yorumlama meselesidir. Bunu açıklamanın işleri daha kolay hale getirdiğini düşünüyorum. İşaretçi aritmetik, 10 değişkenlik bir hafızayla basit bir örnek gösterildiğinde son derece basit ve sezgisel işlemlerdir.


2

Gerçekten yutturduğum açıklama:

Arazi parçaları üzerine inşa edilmiş farklı evleri olan bir şehir şebekesi düşünün. Elinde bir kağıt parçası tutuyorsun. Yazdığınız kağıda:


David'in evi

112 Çok ve çok sokak.


Kağıt parçası (işaretçi değişkeni), David'in evine işaret eden bir adres içerir . Bir arkadaşınıza David'in havalı evine bakmasını söylemek istediğinizde, kağıt parçasını evin referansı olarak kullanmak, postaya asıl iki katlı binayı göndermekten çok daha kolaydır.

Gerçek işaretçilerde olduğu gibi, kağıdınızdaki adresi takip ettiğinizde başınız biraz belaya girebilir. David hareket etmiş olabilir ve oraya gittiğinde yeryüzünde büyük bir delik bulursun. Bu durumda, David taşındığında kağıdın üzerindeki adresi silmek ya da en azından yenisiyle değiştirmek daha iyi olurdu. Ayrıca adrese gidip arkadaşınızın David'in oturma odası olduğunu düşündüğünüzü de girebilirsiniz, ancak bu kez tamamen yabancı bir yüzme havuzuna girersiniz. Başka biri, sahip olduğunuz adresdeki alanı tamamen farklı bir şey için kullandı.


2

İşaretçileri açıklamak istiyorsanız, önce belleği açıklamanız gerekir. Bunu genellikle satır ve sütun içeren grafik kağıdı / kare kağıdı kullanarak yapıyorum. "Öğrenci" hafızayı anlarsa, adresin ne olduğunu anlayabilir. Adresin varsa işaretçilerin var.

Bu soyutlama ile oynayabilirsiniz. Örneğin bir karenin adresini (sayısını) başka bir kareye yazın. Şimdi imleç karesinden hedef kareye bir ok çizin. Şimdi işaretçinin üzerine yazın (örneğin, artırın) ve oku ayarlayın. Başka bir kareye bir adres yazın ve öğrencinin oku çizmesine izin verin ...

Sonraki adım: Belirli karelere (işaretçi gibi) bir ad verin. Şimdi referans düzenlemeyi açıklayabilirsiniz. Bu kadar.


2
Bana, elektronları kullanan elektronları elime geçirmeden önce kullandığım bir "bilgisayarı" hatırlatıyor - karton "CARDIAC" deniyordu. Kelimenin tam anlamıyla, diğer numaralı kutulardan sayıları almak için numaralı kutulara sayılar yazmak O was eğitici ve sorun gerçek mikroişlemcilerinde işaretçileri anlama yoktu.
DarenW

2

Belki de sadece benim, ama analojilerle iyi çalışıyorum. Diyelim ki bir arkadaşınız (işlev / sınıf) "Foo", bir başkası (farklı işlev / sınıf), "Bar", bir nedenden dolayı sizinle iletişim kurmak istersiniz. "Foo", sizi "Bar" ı görmeye götürebilir, ancak bu tüm varlıkları (örneklerin) etrafta dolaştırmak uygun değildir. Ancak, "Foo" telefon numaranızı (işaretçi) "Bar" olarak gönderebilir. Bu şekilde, nerede olursanız olun, "Foo" sizi bulmak zorunda kalmadan sizinle nasıl iletişim kuracağınızı bilir.

Ve diyelim ki "Bar" seninle de temasa geçmek isteyen "Baz" ın bir tanıdığı var. Ancak telefon numaranızı koruyorsunuz ve herkesin sahip olmasını istemiyorsanız, "Baz" "Bar" ı (telefon imleci olarak telefon) çağırabilir; bu durumda aramayı size yönlendirebilir (başka bir işaretçi). Ve böylece “Baz” ın arkadaşlarının ve arkadaşlarının zincirleri.


2

İşaretçiler yapmak yolu Eğer montaj dil ve / veya bilgisayar mimarisi inceledim eğer daha mantıklı. Bir C sınıfını öğretirsem, bellek modelini ve işlemcinin gerçekte gerçekleştirdiği komut türlerini açıklamak için birkaç hafta mimarlıkla başlayacağımı düşünüyorum.


Kesinlikle. Kayıtlarla uğraşırken ve acil değerler ve dolaylı adresleme gibi şeyleri anladığınızda, tüm işaretçiler kavramı sezgiseldir. İlk C satırımı yazmadan önce 6502 düzeneğini ve sonra 68K düzeneğini öğrendim, bu nedenle işaretçilere girdiğimde derleyicinin (ara) düzeneğine baktım ve beklendiği gibi oldu.
Radian

2

Benim "aha!" bu eğitimde şu an geldi:

C İşaretçiler ve Diziler Üzerine Bir Eğitim

Kesin olarak, bu bölümde geldi: Bölüm 3: İşaretçiler ve Dizeler

Daha kesin olmak gerekirse, bu cümleyle geldi:

Puts () öğesine iletilen parametre bir işaretçidir, yani bir işaretçinin değeridir (C'deki tüm parametreler değere göre iletilir) ve işaretçinin değeri işaret ettiği adres veya basitçe bir adrestir. .

Bunu okuduğumda, bulutlar ayrıldı ve melekler trompet uçaklarını patlattı.

Görüyorsunuz, daha önce okuduğum her C dersi ya da kitabı, C'nin değere veya referansa göre, nefret dolu bir yalanla geçebileceğini iddia etmişti. Gerçek şu ki, C her zaman değere göre geçer, ancak bazen geçen değer bir adres olur. Metot içinde, bir kopya, bir int'nin yapıldığı gibi bir kopyanın yapıldığı gibi, bu adresin bir kopyasından yapılır. İşaretçinin işaret ettiği değerin bir kopyası yapılmaz . Böylece işaretçiyi yöntem içinde kullanarak orijinal değere erişebilir ve değiştirebilirsiniz.

Asla C programcısı olmadım, ancak .NET programcısı oldum ve nesneler ve nesne referansları aynı şekilde çalışıyor; nesneye yapılan başvuru değere göre iletilir (ve bu nedenle kopyalanır), ancak nesnenin kendisi kopyalanmaz. Bunu anlamayan birçok programcının etrafında çalıştım çünkü hiç işaretçi öğrenmediler.


1

İşin püf noktası bir şeyin yerinin ve o şeyin kendisinin aynı olmadığını, tıpkı bir boru resminin bir boru olmadığını açıklamaktır . Bir şeyi taşıdığınızda, konumu değişir. Konum kalır ve başka bir şey oraya konulabilir.


1

İşaretçi, yararlı bir şeyin nerede olduğunu söyleyen yapışkan bir nottur. Bir şeyin konumunu içerir ve ne kadar büyük olduğunu söyler (yine de C cinsinden). Bu yüzden çift işaretçi "Buzdolabında altı paket var" yazan yapışkan bir not gibidir. Gerçekten de kola mı Budweiser mi olduğunu bulmak için altı paketi almalısın.


1

Kod verilen:

int v=42; // basit bir değişken bildirme ve başlatma

int *p = &v; // v değişkenine p noktası oluşturma

Yukarıdaki kod hakkında şöyle söylenebilir:

int * p // "int pointer p" ... işte işaretleyiciyi int türündeki değişkene bildirirsiniz

*p // "p ile işaret" ", p nin gösterdiği veriyle aynıdır.

&v // "v değişkeninin adresi" ... bu, p'nin değişmez değerini temsil eder.


1

http://cslibrary.stanford.edu/

Bu site, imleçler ve hafıza yönetimi hakkında harika dersler veriyor.

İşaretçilerle ilgili temel bilgileri, işaretçileri ve sitede verilen hafızayı gözden geçirmenizi öneririm. İşaretçi kavramlarını daha da güçlendirmek için link üzerinde verilen linklere listelenen problemlere de bakabilirsiniz.


1

İşaretçileri açıklamanın anahtarı, açıkladığınız kişilerin zaten hafıza kavramını anlamalarını sağlamaktır. Gerçekten düşük seviyesini anlamaları güzel olurdu, ancak hafızanın büyük bir dizi olarak var olduğuna inanıyor ve dizindeki herhangi bir pozisyona indeks konumuyla ulaşabileceğinizi anlamak yeterli.

Bir sonraki adım, tüm hafızayı kopyalamak yerine indeks lokasyonunu geçmek kavramına sahip olmak çoğu insan için anlamlıdır. Bu, çoğu insanın işaretçilerin neden yararlı olduğunu anlamalarına izin vermek için yeterlidir.

işaretçileri anlamak için son adım, tüm verilerin depolandığı dizin konumunu saklamak için bir parametre olarak bir bellek dizin konumunu nasıl parametre olarak geçirebileceğinizi açıklamaktır. Bazı insanların başa çıkabilmesi için bunun çok ileri bir adım olabileceğini buldum.

Birisi bu temel adımları kavradığında, işaretçileri süresiz olarak zincirleyebildiğinizi kavrayabilmeleri için, gerçek veri nesnesini bulmak için adreslere kaç kez bakmanız gerektiğini takip ettiğin sürece takip edin.

Birisi işaretçileri kavradıktan sonra, hızlıca kavraması gereken bir sonraki şey, yığın belleği ile yığın belleği arasındaki farktır ve yöntemin dışına alındığında bellek yığınlaması için işaretçilerin neden tehlikelidir.


0

"C bulmacaları" ya da benzeri bir kitabı hatırlıyorum, yalnızca okuduğum kitaplıkta yer alan az sayıdaki programlama / bilgisayarla ilgili kitaptan biriydi, C anlayışım ilkeldi. Size bir C ifadesi attı ve daha fazla karmaşıklaşarak genişletmek istedi.


0

Üniversitedeyken profesörüm, bir noktanın kendi başına ayrı bir değişken olarak bir noktayı bir bellek konumuna (bir dizi gibi temsil edilir) okuyla gösteren çok temiz powerpoint slaytlarına sahipti. -yakada, ok değiştiğinde, göstericinin kurallarına göre işaretlendiğinde vb., birinin birkaç dakika içinde anlayamamasının bir yolu yoktu. Konseptin kendisi gerçekten kolaydır, ancak bunu doğru yapmak veya pratik programlarda uygulamak daha fazla pratik gerektirir.


0

Bunu yapmadan önce, "her şey belleği kullanır" programlamada ve bellekteki (statik) değişken dağılımını açıklarım. Bir bellek adresinin ne olduğunu ve bellek alanı, bellek adresi ve değişkenler arasındaki ilişkiyi de açıklayacağım.

Son olarak, tamsayı veri türü ve değişkenleri, dize veri türü ve değişkenleri ... ve bunun gibi, 0 0 "" gibi boş bir değere sahip olan bellek adreslerini saklayan özel bir veri türü olduğunu açıklayana kadar açıklarım. boş çağırdı .

Ve son olarak, işaretçilerin kullanımı yoluyla dinamik olarak ayrılmış değişkenler.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.