C Programlama diliyle şamatalar

Başlatan z, 23 Ekim 2011, 15:32:04

vsalma

hayır aldığın memory otomatik olarak geri verilmez.

controller

free fonksiyonu malloc, calloc ile ayrılan belleği serbest bırakır, lokal değişkenler üzerinde etkisi olmaz sanırım.
Hesabım OG tarafından haksız bir şekilde pasif yapılmıştır.

yamak

#302
Hocam sorunun cevabını buldum aslında. Ayrılan bellek otomatik geri bırakılmıyo. Bırakılması için free kullanılması gerekiyo. Eğer geriye bırakılsaydı, temp adresinin içeriğini printf ile yazdırmazdım. Aslında sorduğum soru mantıksız. Eğer öyle bişey olsaydı fonksiyonlardan geriye fonksiyonun içinde ayrılan yeri adresi hiçbir zaman döndürülmesini bi manası kalmazdı :)

vsalma

Çökmesede güzel bir örnek değil aslında fonksiyon içinde yer alıp onun adresini döndürmek. Yeri dışarıda alıp fonksiyona adresini sokup içerisini fonksiyon içinde doldursanız daha güzel olur. Fonksiyonunuzu çağıran biri sizin içeride memory aldığından haberdar olmayıpgeri iade etmeyebilir. Herkes kendi aldığını kendi bıraksın.

Erdem

Aslında her iki durumda da bellek sızıntısı olur diye düşünüyorum. Yukarıdaki örnekte fonk işlevinden çıkılmadan önce free ile dinamik olarak ayrılan bellek alanının geri verilmesi gerekiyor.

int foo0() { char * p0, *p1;

    p0 = malloc(1);

    if (birSeylerYap(p0))
    {
        free(p0);
        return 1;
    }

    p1 = malloc(1);

    baskaSeylerYap(p0, p1);

    free(p1);
    free(p0);

    return 0;
}

Yukarıdaki 'foo0' işlevinde bellek sızıntısı olmaması, programcının dikkatine kalmıştır. İşlevden çıkılan her noktada bellekten ayrılan bütün alanların geri verilmelerinin unutulmaması gerekir.

Dinamik değişkenler için C'de malloc'la yer ayrılır, ve free ile geri verilir.

C++'da new ile değişken için hem yer ayrılır hem kullanıma hazırlanır, ve delete ile hem sonlandırılır hem bellek geri verilir.

Çöp toplayıcı bulunan bir ortamda ise new ile kurulan bir değişkenin delete ile sonlandırılması gerekmez; çöp toplayıcı ilerideki belirsiz bir zamanda hem değişkenin bozucusunu (destructor) çağırır, hem de belleği geri verir.

C++'da belleğe güvenli bir şekilde erişmek için akıllı göstergeler (smart pointers) veya daha genel ismiyle RAII yöntemleri kullanılır.

http://acehreli.org/turkcecpp/akilli_gostergeler.html

D C++'nin getirdiği RAI gibi yöntemleri desteklerken ek olarak otomatik bellek yönetimin (çöp toplayıcısını) da kullanabiliriz. Buna rağmen D gibi sistem dillerinde alt düzey bellek işlemlerini elle de yönetebiliriz.

http://ddili.org/ders/d/bellek_yonetimi.html

http://ddili.org/makale/bellek.html

cooldoubtless

HOCAM BÜYÜK BİR ZEVKLE TAKİP EDİYORUM ELİMDE KALEM KAĞIT :) AMA BEN YAPTIĞINIZ BİR İŞLEMİ ANLAMADIM ANLAYAN VARSA CEVAP VERİRSE ÇOK SEVİNİRİM..
                    &   |   ^   ~    (Bitwise)

                    &   AND  operatoru
                    |   OR  operatoru

                   ^   XOR  operatoru

                   ~   NOT operatoru

                   A = 0x0A &  0x03;   A nin sonucu 0x02
                   A = 0x0A |  0x03;   A nin sonucu 0x0B
                   A = 0x0A ^  0x03;   A nin sonucu 0x09
                   A = ~0x0A;   A nin sonucu 0x05

HOCAMIZIN VERDİĞİ BU ÖRNEKLERDE SONUNCU ÖRNEĞİN CEVABINI BEN SÜREKLİ 0XF5 BULUYORUM ANCAK HOCAMIZ 0X05 DEMİŞ NEREDE HATA YAPIYORUM?

Erdem

Alıntı yapılan: cooldoubtless - 21 Temmuz 2012, 18:32:03
                   A = ~0x0A;   A nin sonucu 0x05

HOCAMIZIN VERDİĞİ BU ÖRNEKLERDE SONUNCU ÖRNEĞİN CEVABINI BEN SÜREKLİ 0XF5 BULUYORUM ANCAK HOCAMIZ 0X05 DEMİŞ NEREDE HATA YAPIYORUM?

Ben de senin çözümünün doğru olduğunu düşünüyorum. ~A 0xF5 oluyor. Eğer sayı işaretli olsaydı sonuç şu şekilde olurdu.

        -128    64    32      16     8    4    2     1
~A         1      1      1         1     0    1    0     1
=      -128 + 64 + 32 + 16 + 0 + 4 + 0 + 1 == -11

muhittin_kaplan

0x0A= b0000 1010
        ~b1111 0101

serhat1990

Alıntı yapılan: cooldoubtless - 21 Temmuz 2012, 18:32:03
HOCAM BÜYÜK BİR ZEVKLE TAKİP EDİYORUM ELİMDE KALEM KAĞIT :) AMA BEN YAPTIĞINIZ BİR İŞLEMİ ANLAMADIM ANLAYAN VARSA CEVAP VERİRSE ÇOK SEVİNİRİM..
                    &   |   ^   ~    (Bitwise)

                    &   AND  operatoru
                    |   OR  operatoru

                   ^   XOR  operatoru

                   ~   NOT operatoru

                   A = 0x0A &  0x03;   A nin sonucu 0x02
                   A = 0x0A |  0x03;   A nin sonucu 0x0B
                   A = 0x0A ^  0x03;   A nin sonucu 0x09
                   A = ~0x0A;   A nin sonucu 0x05

HOCAMIZIN VERDİĞİ BU ÖRNEKLERDE SONUNCU ÖRNEĞİN CEVABINI BEN SÜREKLİ 0XF5 BULUYORUM ANCAK HOCAMIZ 0X05 DEMİŞ NEREDE HATA YAPIYORUM?

Hata yok çözümün doğru...

cooldoubtless

derslerin devam etmemesinin bir nedeni var mı acaba? bunalmış hocam uzun süredir yazmamış

Erdem

O zaman ben haftanın sorusu tadında bir soru yazayım.

Soru şu : Aşağıdaki program öğrencilerin final notunun %40'ını, arasınav notunun %20'sini, ödevlerin ortalamasının %40'ını alarak bitirme notunu buluyor ama programda bir hata var. Bu hata ne?

Not : Ödev girişini linux altında Ctrl-D ile sonlandırabiliyorsunuz.

#include <iomanip>
#include <ios>
#include <iostream>
#include <string>

using std::cin;         using std::setprecision;
using std::cout;        using std::string;
using std::endl;        using std::streamsize; 

int main ()
{
    // Ogrencinin adini sor ve oku
    cout << "Lutfen isminizi giriniz: ";
    string isim;
    getline (cin, isim);

    cout << "Merhaba, " << isim << "!" << endl;

    // ara sinav ve final notlarini oku
    cout << "Lutfen ara sinav ve final notlarinizi giriniz: ";
    double  arasinav, final;
    cin >> arasinav >> final;

    // odev notlarini ogren
    cout << "Tum odev notlarinizi giriniz\n";
    cout << "Girisi sonlandirmak icin dosya-sonu (CTRL-D) tuslarina basiniz: ";

    // simdiye kadar okunan not sayisi ve toplami
    int sayac;
    double toplam;

    double x;

    while (cin >> x) {
        ++sayac;
        toplam += x;
    }

    // sonucu yaz

    streamsize sonuc = cout.precision ();
    cout << "Bitirme notunuz " << setprecision (3)
         << 0.2 * arasinav + 0.4 * final + 0.4 * toplam / sayac
         << endl;

    return 0;
}

Tagli

toplam sifirlanmamis. Yani baslangic degeri atanmadan kullanilmis.
Gökçe Tağlıoğlu

bocek

bu aslında C şamatası değil de C++ şamatası olmuş.
toplam değişkeninden başka sayac değişkeni de sıfırlanmamış. ancak bazı derleyiciler kendiliğinden ilk değer olarak 0 veriyor diye biliyorum. böyle bile olsa ilk değeri kendimiz vermeliyiz.
bir de sonuc isimli değişkene atama yapılmış ama kullanılmamış. yapılan atama da ondalık sayılarda noktadan sonra gösterilecek hane sayısı.
belki de precision değerini eski haline getirmek için kullanılacaktı ama unutulmuş.
cout.precision(sonuc);

1 ya da 0. işte 'bit'ün mesele..

Erdem

#313
Alıntı yapılan: bocek - 26 Temmuz 2012, 16:37:33
toplam değişkeninden başka sayac değişkeni de sıfırlanmamış. ancak bazı derleyiciler kendiliğinden ilk değer olarak 0 veriyor diye biliyorum.

Evet buradaki hata ilklendirilmemiş yerel değişkenlerin kullanılması.

Yerel değişkenler açık olarak ilklendirilmezse varsayılan ilklendirme yapılır. Ancak burada derleyicinin verdiği ilk değer tanımsızdır. Ama hangi değişkenler için tanımsızdır. Hazır veri tipleri için.

Tanımsız değişkenlerle yapılabilecek tek geçerli işlem de giriş akımından bir değer okutmaktır. Burada arasinav ve final değişkenlerinde olduğu gibi. Hatta iyi bir programlama alışkanlığı olarak ben bu değerleri de ilklendirerek kullanmayı tercih ediyorum.

Kullanıcı tanımlı türlerde ise, açık ilklendirme yapılmadığı zaman sınıfın varsayılan kurucu işlevi çağrılır. Örneğin burada string ilklendirilmediği için string sınıfına ait varsayılan kurucu (default constructor) çağrılır.

Programı ilk haliyle denediğimizde notlar 100 100 100 olarak girilse bile ortalamayı 60 olarak veriyor. gcc üzerinde denedim.

Programın düzeltilmiş hali:
#include <iomanip>
#include <ios>
#include <iostream>
#include <string>


using std::cin;         using std::setprecision;
using std::cout;        using std::string;
using std::endl;        using std::streamsize; 

int main ()
{
    // Ogrencinin adini sor ve oku
    cout << "Lutfen isminizi giriniz: ";
    string isim;
    getline (cin, isim);

    cout << "Merhaba, " << isim << "!" << endl;

    // ara sinav ve final notlarini oku
    cout << "Lutfen ara sinav ve final notlarinizi giriniz: ";
    double  arasinav, final;
    cin >> arasinav >> final;

    // odev notlarini ogren
    cout << "Tum odev notlarinizi giriniz\n";
    cout << "Girisi sonlandirmak icin dosya-sonu (CTRL-D) tuslarina basiniz: ";


    // Programlama hatasi !
    // Ilklendirilmemis yerel degiskenler

    int sayac = 0;        // <--
    double toplam = 0;    // <--


    double x;

    while (cin >> x)
    {
        ++sayac;
        toplam += x;
    }

    // sonucu yaz

    streamsize sonuc = cout.precision ();
    cout << "Bitirme notunuz " << setprecision (3)
         << 0.2 * arasinav + 0.4 * final + 0.4 * toplam / sayac
         << endl;

    return 0;
}


mesaj birleştirme:: 26 Temmuz 2012, 23:38:18

Evet bir soru daha  :D

Soru : Verilen bir sayının 2'nin üssü olup olmadığını bulan bir işlev yazınız.

Erdem

Bu sorunun cevabı da şu şekilde olacak:
bool ussuMu (int sayi)
{
    return !((~(~0 >> 1) | sayi) & (sayi - 1));
}