2013-05-06 30 views
8

Ben Objective-C ile kapalı başlayarak, programlamaya yeniyim ama daha atmadan önce temelleri geri gitmek için karar verdik. C'ye biraz zaman harcıyorum ve işaretçi karışıklığı ile mücadele ediyorum. Sorum şu: K & R'nin fgets uygulamasının nasıl yapıldığını anlatıyor (p165, 2. baskı) Aşağıdaki kod, yorumlarımın bir çiftiyle doğrudan metinden geliyor.fgets uygulaması (K & R)

char* fgets(char* s, int n, FILE *iop) 
{ 
    register int c; 
    register char* cs; 
    cs = s; 

    while(--n > 0 && (c = getc(iop)) != EOF) 
    { 
    // put the input char into the current pointer position, then increment it 
    // if a newline entered, break 
    if((*cs++ = c) == '\n') 
     break;   
    } 

    *cs = '\0'; 
    return (c == EOF && cs == s) ? NULL : s; 
} 

1) Bu kullanım girişi depolamak, bulunduğu yer ile fgets işlevine, bir char * s geçmektedir. Neden yerel char * cs'yi bildirmeye ihtiyaç duyuyorsunuz - ve sonra bunu s için başlıyoruz? Neden if deyiminde doğrudan doğrudan/manipüle edemiyoruz? Cs ss olarak başlıyor olarak görülüyor, tam olarak aynı şeyi cs chars ekleyerek değil mi? işlevin döndürdüğü bir test cs == s olmadığını görmek için yapılır yukarıdaki İle Bağlı

2) .... Bu neden gerekli?

ben çok temel bir şey eksik olabilir düşünüyorum - Ben SO kontrol etti ve Google'ı ama oldukça onu anlamaya olamaz. Teşekkürler!

+2

"Objective-C ile yola çıkmak ancak daha ileri gitmeden önce temellere geri dönmeye karar verdik" - mükemmel, ** her yeni başlayan bunu yapmalıdır. ** –

+1

Sadece bir çeşit adım atıyormuş gibi hissetmeye başlamıştım Obj-C. C'ye geri döndüğümden beri, tekrar tam bir klutz gibi hissediyorum, ama tekrar tekrar bölüme parçalama hataları ve garip program davranışına karşı vurarak rağmen, bu kesinlikle çabaya değer. – drjimmie1976

+0

Kesinlikle buna değer. Objective-C'yi anlamak için Mastering C kaçınılmazdır. –

cevap

7

Çünkü son satırında, cs == s üzerindeki denetimin bu. Bu karşılaştırma, herhangi bir karakter okuyup okumadığımızı görmek için değiştirilen işaretçiyi cs orijinal s ile karşılaştırır. Eğer yapmadıysak, NULL döndürürüz. Orijinal işaretçi s boyunca cs kullanarak

korunur. Eğer s doğrudan manipüle edildi ise (*cs++ yerine *s++), herhangi bir karakterin okunup okunmadığını kontrol etmenin başka bir yolunu bulmak zorundayız.

biri yalnız işlev parametreleri bırakıp const olarak onları tedavi etmenin yararlı olduğunu da iddia edebilirsiniz. Bazı programcılar bu uygulamayı kod netliğini arttırmanın bir yolu olarak izlerler.

+0

Çok teşekkürler John. Bu, niyetini daha açık hale getirir, fakat eğer 'cs' 'cs = s' ile atandığında, imleyicilerin tam olarak aynı bellek alanına işaret ettiklerini düşünürsem birkaç soru daha yapardım; bu nedenle, '* cs ++' yapmak, '* s ++' ile tam olarak eşdeğer olacaktır. Bu varsayım yanlış mı? – drjimmie1976

+0

Üzgünüz, yorumum zaman aşımına uğradı, ve ben de yanlış yorum yorumu yapıyorum .... Bu yüzden final çizgisini anlamadım. Her iki işaretçinin de "paylaşım" olduğunu görmeyi düşündüm, sonra c == cs ifadesi değerlendirildiğinde aynı olurdu. Şimdiden teşekkürler. – drjimmie1976

+0

@ GasMan14 Ödevden sonra aynı adrese işaret ediyorlar, doğru. '' cs ++ '' s' değiştirmez. Önceliği anladığınızdan emin olun: '* cs ++', * (cs ++) 'değil' (* cs) ++ 'değerine eşittir. cs ++ 'cs', bir sonraki adrese işaret ederek,' '' adrese yönlendiren dereferencesgerleri belirtir. 's' değiştirilmez, çünkü' s' ve 'cs' iki ayrı değişkendir. Eğer ifade '(* cs) ++' ise, o zaman * * s 'değerini değiştirir. (Dikkat et, s değil, ama 's s.) –