İçeriğe geç
academia.sh

Ders 13 / 13

Girdi/Çıktı

Bir biçim dizesinin metni derlemede bellidir ama ne anlama geldiği ancak koşumda belli olur: dokuz gözlemin biri ön işlemcide, ikisi derleyicide, biri bağlayıcıda, beşi koşumda karara bağlanıyor. Sınırlayıcı ölçüm, biçim dizesi ile argümanların uyumunu dilin kendisinin garanti etmediğini gösteriyor.

Yayın Güncelleme

Bu derste

  • Bir biçim dizesinin hangi parçasının derlemede, hangisinin koşumda karara bağlandığını ölçer
  • Yazma işlevlerinin dönüş değerini okuyup kesilen yazımı fark eder
  • Metinden okumanın kaç alan atadığını sayarak başarısız okumayı ayırt eder
İçindekiler

Kurs boyunca sorulan soru hep aynıydı: bu karar hangi aşamada veriliyor. Girdi ve çıktı, o soruyu tek bir satırda dört aşamaya birden dağıtabildiği için kursun kapanışına uygun düşüyor. Bir yazma çağrısında biçim dizesindeki bir makro ön işlemcide yerine konur, dizenin metni derlemede sabitlenir, çağrılan işlevin tanımı bağlamada bulunur ve dizenin ne anlama geldiği ancak koşumda belli olur.

Bu ders o dağılımı ölçüyor. Ölçüm çekirdeğin veriden hesaplanan deger satırının bıraktığı yerden devam ediyor: orada bir toplam koşumda hesaplanmıştı, burada o toplamın nasıl yazıldığı soruluyor.

Dokuz Gözlem

// girdicikti.c — bir bicim dizesinin hangi asamada karara baglandigi
#include <stdio.h>
#include <string.h>

#define ETIKET "olcum"

static void gozle(const char *ad, const char *asama, const char *kanit) {
    printf("%-34s%-12s%s\n", ad, asama, kanit);
}

int main(void) {
    char tampon[64];
    char kucuk[8];

    printf("%-34s%-12s%s\n", "gozlem", "asama", "kanit");

    /* on islemci */
    snprintf(tampon, sizeof tampon, "%s basligi metne kondu", ETIKET);
    gozle("bicim dizesindeki makro", "on islemci", tampon);

    /* derleyici */
    snprintf(tampon, sizeof tampon, "eleman sayisi %d", (int)(sizeof tampon / sizeof tampon[0]));
    gozle("tampon uzunlugu", "derleyici", tampon);

    const char *sabit = "deger: %d";
    snprintf(tampon, sizeof tampon, "metin %d karakter", (int)strlen(sabit));
    gozle("bicim dizesinin metni", "derleyici", tampon);

    /* baglayici */
    gozle("bicimleme islevinin tanimi", "baglayici", "kaynakta tanim yok, cagri yine de cozuldu");

    /* kosum */
    int deger = 42;
    const char *bicim = (deger < 100) ? "%d" : "[%d]";
    snprintf(tampon, sizeof tampon, bicim, deger);
    gozle("bicim dizesinin secimi", "kosum", tampon);

    int genislik = (int)strlen("dort") + 1;
    snprintf(tampon, sizeof tampon, "%*d", genislik, deger);
    gozle("alan genisligi argumani", "kosum", tampon);

    int istenen = snprintf(kucuk, sizeof kucuk, "%s", "merhaba dunya");
    snprintf(tampon, sizeof tampon, "istenen %d yazilan %d", istenen, (int)strlen(kucuk));
    gozle("kesilen yazim", "kosum", tampon);

    int okunan = 0, sayi = 0;
    okunan = sscanf("sicaklik 21 derece", "sicaklik %d", &sayi);
    snprintf(tampon, sizeof tampon, "atanan alan %d deger %d", okunan, sayi);
    gozle("metinden okuma", "kosum", tampon);

    int eslesmeyen = sscanf("sicaklik yirmibir", "sicaklik %d", &sayi);
    snprintf(tampon, sizeof tampon, "atanan alan %d", eslesmeyen);
    gozle("eslesmeyen okuma", "kosum", tampon);

    printf("\n%-12s%d\n", "on islemci", 1);
    printf("%-12s%d\n", "derleyici", 2);
    printf("%-12s%d\n", "baglayici", 1);
    printf("%-12s%d\n", "kosum", 5);
    printf("toplam gozlem: %d\n", 9);
    return 0;
}
gozlem                            asama       kanit
bicim dizesindeki makro           on islemci  olcum basligi metne kondu
tampon uzunlugu                   derleyici   eleman sayisi 64
bicim dizesinin metni             derleyici   metin 9 karakter
bicimleme islevinin tanimi        baglayici   kaynakta tanim yok, cagri yine de cozuldu
bicim dizesinin secimi            kosum       42
alan genisligi argumani           kosum          42
kesilen yazim                     kosum       istenen 13 yazilan 7
metinden okuma                    kosum       atanan alan 1 deger 21
eslesmeyen okuma                  kosum       atanan alan 0

on islemci  1
derleyici   2
baglayici   1
kosum       5
toplam gozlem: 9

TS14. ETIKET makrosu biçim dizesine derleyici kaynağı görmeden önce kondu. Ön işlemci için bu bir metin birleştirmesidir; dizenin bir biçim dizesi olduğunu bilmez, %s ile %d arasındaki farkı da bilmez. Bu yüzden makroyla kurulan bir biçim dizesi, argüman listesiyle uyuşmasa bile ön işlemci aşamasını sorunsuz geçer.

TS15. Tampon uzunluğu derlemede bellidir: sizeof tampon / sizeof tampon[0] bir sabit ifadedir ve 64 verir. Dizinin uzunluğunun derlemede bilindiği Diziler ve Dizgiler dersinde ölçülmüştü; burada aynı bilgi bir yazma çağrısının sınırı olarak kullanılıyor. Biçim dizesinin metni de aynı sınıfa düşer — deger: %d dokuz karakterdir ve bu sayı kaynaktan okunur, koşumdan değil.

TS16. Biçimleme işlevinin tanımı kaynakta yok. Yalnız başlık dosyasından gelen bildirimi var ve çağrı buna rağmen çözüldü: tanımı bağlayıcı buldu. Bu, Fonksiyonlar dersindeki baska birimdeki islev satırının aynısıdır; tek fark, tanımın bu kez ayrı bir kaynak biriminde değil, dilin standart kitaplığında olmasıdır.

TS17. Kalan beş gözlem koşuma düşüyor ve hepsinin ortak yanı şu: kaynak metni değişmeden sonucun değişebilmesi. Biçim dizesi bir koşula göre seçildi (deger < 100 doğru olduğu için köşeli ayraçsız biçim kullanıldı), alan genişliği bir argümandan geldi (dort beş karakterlik bir alan açtı), yazma kesildi, bir metinden bir sayı okundu ve bir okuma hiçbir alan atayamadı.

Dönüş Değeri Ne Söylüyor

TS18. Kesilen yazım satırı, dönüş değerinin ne olduğunu gösteriyor: istenen 13 yazilan 7. Yazma işlevi, tampona sığdırabildiği karakter sayısını değil, sığdırmak isteseydi kaç karakter yazacağını döndürüyor. On üç karakterlik metin sekiz baytlık tampona konduğunda yedi karakter ve bir sonlandırıcı yazıldı, ama dönüş değeri on üç kaldı. Bu iki sayının ayrışması, kesilmenin olup olmadığını anlamanın tek belirlenimci yoludur: dönüş değeri tampon uzunluğundan küçükse yazım tamdır.

TS19. Okuma tarafında dönüş değeri başka bir şey sayıyor: kaç alanın atandığını. Aynı biçim dizesi bir metinde bir alan atadı, ötekinde sıfır. İkinci metin de geçerli bir metindi ve program çökmedi — yalnız sayi değişkeni dokunulmamış kaldı. Okumanın başarısızlığı bir hata değeriyle değil, bir sayımla bildiriliyor ve o sayıyı okumayan bir kaynak, atanmamış bir değişkeni atanmış sanır.

Sınırlayıcı Ölçüm

TS20. Biçim dizesi ile argümanların uyumunu dilin kendisi garanti etmez. Yukarıdaki ölçümde biçim dizesi bir yerde bir değişkenden geldi — koşula göre seçilen bicim işaretçisi. O çağrıda derleyicinin elinde, dizenin içeriğine bakarak argümanları denetleyecek bir bilgi yoktu; dize koşumda seçiliyordu. Biçim dizesi kaynakta yazılı bir sabit olduğunda derleyicinin elinde uyumu denetleyecek bilgi vardır ve yaygın derleyiciler bunu isteğe bağlı bir uyarı olarak sunar. Denetimin kendisi dilin bir garantisi değildir: standart, argümanın biçim belirleyicisiyle uyuşmamasını doğrudan tanımsız davranış sayar ve hiçbir denetim öngörmez. Dize bir değişkenden geldiğinde o bilgi de kalmaz — denetim düşer ve sorumluluk tümüyle yazana geçer.

Bu, kursun dört aşamalı sorusunun en keskin sonucudur: aynı çağrı, biçim dizesinin nereden geldiğine göre derleyici sınıfından koşum sınıfına kayar. Kaynak metni neredeyse aynıdır; değişen tek şey, bir bilginin hangi aşamada elde bulunduğudur.

Kapanış Tablosu

On üç ders boyunca ölçülen kararlar aşağıda toplanıyor. Aşama hücresi her dersin kendi metninde yazılı olandan alınmıştır; birden çok aşama ölçen dersler ikisini de taşır.

Ders Ölçülen karar Aşama Sınırlayıcı ölçüm
C’nin Konumu Çekirdeğin on dört gözleminin dağılımı dördü birden Dört aşama bir karmaşıklık değil, dört ayrı denetim noktasıdır
Derleme Aşamaları Her aşamadan birer satırın yan yana koşumu dördü birden Aşamalar sırayla çalışır ve geri dönmez; ön işlemcinin ürettiği metni derleyici düzeltmez
Başlık Dosyaları Bildirimin metin olarak kopyalanması ön işlemci · bağlayıcı Başlık dosyası bir sözleşme değildir; bildirimle tanımın uyumunu dil denetlemez
Ön İşlemci Makronun tip bilmeden metin koyması ön işlemci Makro bir işlev değildir; argümanı birden çok kez yerine konabilir
Derleyici Uyarıları ve Standartlar Uyarının hangi aşamada doğduğu derleyici Uyarı bir hata değildir ve uyarısız derlenen bir program doğru sayılmaz
Veri Tipleri Tip aralığı ve tam sayı yükseltmesi derleyici Taşma davranışı tipin işaretine bağlıdır: işaretsizde tanımlı, işaretlide tanımsız
Değişkenler, Kapsam ve Ömür Adın görünürlüğü ile değerin yaşadığı süre derleyici · koşum · bağlayıcı Aynı ad iki birimde iki ayrı nesne olabilir; bunu belirleyen bağlayıcıdır
İşleçler İşlecin tipe göre anlam değiştirmesi derleyici Öncelik gruplamayı belirler, değerlendirme sırasını her zaman belirlemez
Denetim Akışı Hangi dalın izlendiği koşum · ön işlemci Hangi dalların var olduğu koşumla değil, ön işlemciyle belirlenmiş olabilir
Fonksiyonlar Çağrının tanıma bağlanması bağlayıcı Bildirimle tanımın birimler arası uyuşmazlığını ne derleyici ne bağlayıcı denetler
Diziler ve Dizgiler Dizi uzunluğu ile dizgi uzunluğu derleyici · koşum Dizinin uzunluğu derlemede bellidir ama bu bilgi işleve geçmez
Yapılar, Birlikler ve Numaralandırmalar Alanların yerleşimi ve sabitlerin değeri derleyici Birlik, hangi alanın en son yazıldığını kendi başına izlemez
Girdi/Çıktı Biçim dizesinin yorumlanması koşum Biçim dizesi bir değişkenden geldiğinde derleyicinin uyum denetimi düşer

Özet

  • Bir yazma çağrısı dört aşamayı birden taşıyabiliyor: makro ön işlemcide, tampon uzunluğu ve dizenin metni derleyicide, işlevin tanımı bağlayıcıda, dizenin anlamı koşumda karara bağlandı.
  • Dokuz gözlemin biri ön işlemcide, ikisi derleyicide, biri bağlayıcıda, beşi koşumda ölçüldü; girdi çıktı, kursun dört sınıfının en yoğun karıştığı yerdir.
  • Yazma işlevinin dönüş değeri yazılan karakter sayısı değil, yazılmak istenen sayıdır: on üç istendi, yedi yazıldı, dönüş on üç kaldı.
  • Okuma işlevinin dönüş değeri atanan alan sayısıdır; sıfır dönen bir okumada hedef değişken dokunulmamış kalır ve bunu fark etmenin tek yolu o sayıyı okumaktır.
  • Biçim dizesi kaynakta sabitken derleyici argüman uyumunu denetleyebiliyor; dize bir değişkenden geldiğinde aynı çağrı koşum sınıfına kayıyor ve denetim düşüyor.

Kurs Kapanışı

On üç ders boyunca tek bir soru soruldu: bu karar hangi aşamada veriliyor. Ortak tanımın on dört gözlemi 4 ön işlemci, 4 derleyici, 3 bağlayıcı, 3 koşum olarak dağılmıştı ve bu dağılım kurs boyunca değişmedi — değişen, hangi düzeneğin hangi sınıfa düştüğüydü.

Dil ve Derleme konusu soruyu kaynağın programa dönüşme yoluna sordu: dört aşamanın varlığına, bildirimlerin metin olarak paylaşılmasına, ön işlemcinin tip bilmemesine ve uyarının nerede doğduğuna. Temel Sözdizim konusu aynı soruyu dilin kendi yapılarına taşıdı: bir tipin taşıdığı değere, bir adın görünürlüğü ile bir değerin ömrünün ayrı sorular olmasına, bir işlecin tipe göre anlam değiştirmesine, bir çağrının nerede çözüldüğüne, bir uzunluğun ne zaman bilindiğine ve bir kayıt tipinin alanlarının nasıl yerleştiğine.

Kursun en çok tekrarlanan tek bulgusu şudur: aynı kaynak metni, bir bilginin hangi aşamada elde bulunduğuna göre farklı davranır. Bir dizi uzunluğu derlemede bilinir, bir dizgi uzunluğu koşumda; bir makro tip bilmez, bir derleyici bilir; bir ad iki birimde aynı yazılır ama aynı nesne olmayabilir.

Sıradaki kurs belleğe ve işaretçilere bakıyor: bir değerin nerede durduğu, kim tarafından ayrıldığı ve ne zaman bırakıldığı. C’de bu soruların hepsi kaynakta yazılıdır ve hiçbiri kendiliğinden denetlenmez.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ ↵ Esc gezin · aç · kapat