Thread overview
auto
Aug 27, 2022
Cos00kun
Aug 27, 2022
Cos00kun
Aug 27, 2022
Ali Çehreli
Aug 28, 2022
Salih Dincer
Aug 29, 2022
Cos00kun
Aug 27, 2022
Ali Çehreli
Aug 27, 2022
Cos00kun
August 27, 2022

Merak ettiğim bir konu var.

  int degisken;
veya
  auto degisken;

  Sadece merakımdan soruyorum; Şimdi "int" ile bellekte tanımlanmış "int" değişken alanı kadar yer ayırıyor ancak "auto" ile degisken tanımlandığında bellekte ne oluyor ? iki seçenek var sanki birincisi hiç yer ayrılmıyor ancak bir atama yapıldığında program önce o atamadaki verinin türü neyse onu araştırıp buluyor sonrasında bellekte o değişken tipi kadar byte ayırıyor ya da direkt en büyük byte değişkeni kadar yer ayırıyor ki tanımlanan veri oraya sığsın.
nasıl oluyor ?

Bir ikinci sorum ise eğer auto anahtar kelimesi eğer değişkenle atanan verinin türünü araştırıp buluyor ise bu durumda bir maaliyet doğuyor mu ? yani mikro düzeyde bile olsa bir zaman kaybı oluyormu?

August 27, 2022

unuttuğum bir şey daha vardı yukarıdaki konuyla ilgili;
D dilimizin kurallarından biri gereği tüm değişkenler tanımlandıkları anda ilklenirler ilkesini düşündüğümüzde bu durumda "auto" yu nereye koymalıyız ?

August 27, 2022
On 8/27/22 00:05, Cos00kun wrote:
> Merak ettiğim bir konu var.
>
>        int degisken;

Derleyici kodu 'degisken' için 4 baytlık yer kullanılacak biçimde derliyor. Örneğin,

  degisken = 42;

dendiğinde onu şöyle derliyor:

  SP - 4 adresine 42 yaz

>      veya
>        auto degisken;

O yasal bir kod değil çünkü tür belli değil (derlenemez). Ama şöyle olabilirdi:

  auto degisken = 3;

Ve 3 bir int olduğundan 'degisken' de int olurdu.

Not: Aslında 'auto' şart değildir. Örneğin duruma göre şunlar da olur:

  immutable degisken = 3;
  const degisken = 3;
  static degisken = 3;
  shared degisken = 3;
  // vs.

Hepsinde de 'degisken' int'tir.

D'de 'auto'yu başka anahtar sözcük bulunmadığı zaman kullanıyoruz. (D, bu konuda C++'tan farklı.)

> "auto" ile degisken
> tanımlandığında bellekte ne oluyor ?

auto (veya başka çeşit) çıkarsamada hiçbir özellik yok. Tür ne ise o kadarlık bayt kullanılacağına karar veriliyor.

> bir atama yapıldığında program önce o atamadaki
> verinin türü neyse onu araştırıp buluyor sonrasında bellekte o değişken
> tipi kadar byte ayırıyor

Statik türlü (ve dolayısıyla derlemeli) dillerde programın çalışması sırasında öyle arama yapılmaz.

> ya da direkt en büyük byte değişkeni kadar yer
> ayırıyor ki tanımlanan veri oraya sığsın.

En büyük bayt değil, o tür için tam olarak ne kadar bayt gerekiyorsa o kadar yer ayırıyor. Şöyle bir işlev olsun:

int foo(int a, int b) {
  int c = a + b;
  int d = a * b;
  return c + d;
}

'c' için yer ayrılıyor diyoruz ama çalışma zamanında hiç yer ayrılmıyor. Programın "disassembly"sine bakalım. Ben hazırda bulunduğu için şimdi 'objdump' kullanıyorum. Onun yerine başka programlar veya godbolt gibi siteler de kullanılabilir:

$ objdump -d deneme > deneme.asm

deneme.asm dosyasını açıyorum ve içinde "foo" arayarak o işlevin derlenmiş halini buluyorum (derlerken -O kullanMAdım çünkü o zaman kodlar çok başka olurdu). Sağdaki sayıları ben şimdi elle yazdım:

00000000000e4bfc <_D6deneme3fooFiiZi>:
   e4bfc:	55                   	push   %rbp
   e4bfd:	48 8b ec             	mov    %rsp,%rbp                   1
   e4c00:	48 83 ec 20          	sub    $0x20,%rsp
   e4c04:	89 7d f0             	mov    %edi,-0x10(%rbp)
   e4c07:	89 75 f8             	mov    %esi,-0x8(%rbp)
   e4c0a:	8b 45 f8             	mov    -0x8(%rbp),%eax             4
   e4c0d:	8b 4d f0             	mov    -0x10(%rbp),%ecx            3
   e4c10:	8d 14 08             	lea    (%rax,%rcx,1),%edx
   e4c13:	89 55 e8             	mov    %edx,-0x18(%rbp)
   e4c16:	0f af c1             	imul   %ecx,%eax                   2
   e4c19:	89 45 ec             	mov    %eax,-0x14(%rbp)
   e4c1c:	8d 04 02             	lea    (%rdx,%rax,1),%eax
   e4c1f:	c9                   	leave
   e4c20:	c3                   	ret
   e4c21:	00 00                	add    %al,(%rax)

Alışık olmayanlara çok karışık gelecektir ama burada önemli olan, rsp yazmacıdır. İçindeki "sp", "stack pointer"dan geliyor ve "r" de "register" (yazmaç) anlamına geliyor. Yani, çağrı yığıtı olan ve "stack" dediğimiz yeri gösteren yazmaç...

Sağdaki numaraları açıklıyorum:

1) rsp'nin değeri, rbp adlı başka bir yazmaca atanıyor

2) imul, "multiply" ile ilgili; orada ecx ile eax çarpılıyor. (Yani, koddaki 'a' ve 'b' değişkenleri.) Ama dikkat ederseniz, ecx ve eax yazmaçları sırasıyla şuralardan ediniliyorlar:

3)  -0x10(%rbp),%ecx

4)  -0x8(%rbp),%eax

Baş taraflarının anlamı da örneğin şu: rbp'nin gösterdiği yerin 0x10 öncesi (çünkü eksi 0x10), vs.

Yani, derlenmiş olan kodun içinde değişken isimleri değil, onlar için stack'in neresinin kullanılacağı başından hesaplanmış durumda. foo() çağrıldığında stack ne olursa olsun, onun 0x10 ve 0x18 öncesi o değişkenler için kullanılacak diye kesinleşmiş (derleme zamanında).

Yani, çalışma zamanında yer ayırma masrafı yok.

0x10 ve 0x18 gibi değerlerin bilinebilmesi için türlerin uzunlukları gerekiyor. D gibi statik türlü dillerde bu iş derleme zamanında hallediliyor.

> Bir ikinci sorum ise eğer auto anahtar kelimesi eğer değişkenle atanan
> verinin türünü araştırıp buluyor ise bu durumda bir maaliyet doğuyor mu

Derleme zamanında sıfıra yakın maliyet, çalışma zamanında sıfır maliyet...

Ali

August 27, 2022
On 8/27/22 00:12, Cos00kun wrote:
> tüm değişkenler tanımlandıkları
> anda ilklenirler ilkesini düşündüğümüzde bu durumda "auto" yu nereye
> koymalıyız ?

Ben şöyle yapıyorum:

Eğer değer kullanacaksam:

  auto a = 42;
  auto b = BirYapı(1.5);
  auto c = new BirSınıf("falan");

Eğer değer kullanmayacaksam

  int a;
  BirYapı b;
  BirSınıf c;

Ali

August 27, 2022
On Saturday, 27 August 2022 at 07:40:07 UTC, Ali Çehreli wrote:
> ....
> ....
> Derleme zamanında sıfıra yakın maliyet, çalışma zamanında sıfır maliyet...
>
> Ali

Yine döktürdün değerli bilgiler için çok teşekkür ederim :) olayı anladım.
bende zamanında Assambler ve ollydebug programıyla ile haşır neşir olduğumdan ne demek istediğini tam olarak anladım Ali hocam sağol.

August 28, 2022

On Saturday, 27 August 2022 at 07:12:58 UTC, Cos00kun wrote:

>

unuttuğum bir şey daha vardı yukarıdaki konuyla ilgili;
D dilimizin kurallarından biri gereği tüm değişkenler tanımlandıkları anda ilklenirler ilkesini düşündüğümüzde bu durumda "auto" yu nereye koymalıyız ?

Ali hocamız gerekenleri anlatmış ve onun üzerine sözüm yok ama bir laf [*] edeyim dedim auto'dan içeri. Derim ki auto'ya çok güvenmemek lazım ve gerektiğinde açıkca tarif etmeli. Tıpkı araba kullanırken navigasyona çok güvenip de bizi bozuk/daracık yollara sokması gibi :)

Farkı gösteren çiftli örnekle adım adım gidelim...

Önce TEST_ok isminde şöyle özel bir türümüz olsun ve buna çok da takılmayalım çünkü takma adı sayesinde aslında char sarması. Etsiz olan, prinçli :)

struct TEST_ok {
    char c = 'd';
    alias c this;
}


import std.stdio;


struct TEST_ops {
    char c = 'd';
    alias d this;

    char d()
    {
        return c;
    }
}

void main()
{
    TEST_ok ok;
    auto test1 = ok;

    test1.writeln; //d
    assert(is(typeof(test1) == TEST_ok));

    TEST_ops ops;
    auto test2 = ops;

    test2.writeln; // TEST_ops('d')
    assert(is(typeof(test2) == TEST_ops));
}

Bir de TEST_ops isminde başka bir yapımız var ki işlerin yolunda gitmediği diğer dolmamız. Bu biraz etli ama daha lezzetli :)

Neyse, yemeği seven biri olduğum belli olmasın. Oldu mu yoksa!

Şimdi test1 ve test2'miz var ve bu ikisi de 'd' karakterini tutmasını istiyorum çünkü kendi türümde bir char'a bağladım. Ben bunu çok sık yaparım ama auto kullanırsam her ikisinde de derleyici kopyasını çıkarmak istediğimi zannedecek. Oysa örneklar arası fark, teoride yapı içinde gibi (dikkat: pratikte yapıya bağlanmış ve onun üzerinden erişilebilen tek başına) işlev aslında. En iyisi mi farkı önce ekranda görelim!

Kodu derlediğinizde ekrana gelen sonucun alt alta d harfi olması için test2'yi açıkca char olduğunu belirtmeniz gerekiyor. Yoksa d() işlevi üzerinden döndürülen karakteri ekrana basacağımızdan kopyanın varsayılan toString() çalıştırılıyor. Bu tercihi yapan write() ailesi (sanırım formattedWrite)?

Özetle, örnekte aslında 4 yapı nesnesi var ama bana lazım olan içindeki veri. O yüzden tüm auto'ları char olarak değiştirmek veya açıkca üye değişkeni belirtmek gerekiyor. Yoksa gereksiz kopyalarını almış oluyoruz. Zaten writeln() ile ekrana yazarken de kopyası alınıyor. Neyse çok çok uzattım sanırım!

Başarılar...

[*] Geleneklerimizde 'söz' değerli, 'laf' ise tıpkı temizlik yapılırken önemsiz görülen çer/çöp halı altına atılması gibi değersizdir.

August 29, 2022

On Sunday, 28 August 2022 at 00:12:42 UTC, Salih Dincer wrote:

>

ile ekrana yazarken de kopyası alınıyor. Neyse çok çok uzattım sanırım!

Eskiden bu kadar yemeklerle ilgili değildin :)
Sağolasın bilgiler için ayrıa lafı falanda uzatmadın yemeklerle programlamayı birleştirmek fena olmamış