Thread overview
Öğrenmelik: opIndex() içermeyen yapı!
May 24

Yapı bir dizi değil ki! Yasal mı, bu nasıl olur? Şöyle bir kod parçası var; deneysel bir programdan alınma:

import std.stdio;
struct BirYapı { int[] i; }
void main()
{
    auto b = new BirYapı(new int[2]);
    b[0].writeln(": @", &b[0]);
} /* ÇIKTISI:
BirYapı([0, 0]): @7FDDB2F83000
*/

İçeriğinde opIndex() tanımlanmadığı için merak ettim. Sanırım ilk elemanın adresi aslında yapının, yoksa içindeki diziye eriştiğimiz söylenemez, değil mi?

Teşekkürler...

May 24

On Tuesday, 24 May 2022 at 05:26:34 UTC, Salih Dincer wrote:

>

Yapı bir dizi değil ki! Yasal mı, bu nasıl olur?

Ben böyle bir şey bilmiyordum! Anladığım kadarıyla yasal! İşin ilginci kodu geliştirdiğimde ikinci bir null üye gördüm. Çünkü int[] i yanına, yeni bir üye işlev olan int opIndex() eklendiğinde ortaya çıktı:

void main()
{
  struct BirYapı
  {
    int[] i;
    int opIndex(size_t index) { return i[index]; }
  }
  auto b = new BirYapı(new int[2]);
  b.i[1] = 1;

  import std.stdio;
  b[0].writeln(": @", &b[0]);
  foreach(n, ref a; b.i)
  {
    n.writeln(": @", &a);
  }

  auto i = BirYapı([1, 2, 3]);
  assert(i[0] == 1);
  assert(i[1] == 2);
  assert(i[2] == 3);
} /* ÇIKTISI:
BirYapı([0, 1], null): @7F4274288000
0: @7F4274289000
1: @7F4274289004
*/

Bir şey daha, sanırım (yok eminim! 😀) yapıyı new operator ile kurmadığınızda bu köşeli parantez olayı olmuyor. Çünkü şu hatayı alıyorum:

>

globalVar.d(50): Error: no [] operator overload for type BirYapı

Anladığım kadarıyla new ile kurunca yapının her üyesine bu şekilde erişmek mümkün!?

Allah Allah!!!

May 24
On 5/23/22 22:26, Salih Dincer wrote:

>      auto b = new BirYapı(new int[2]);
>      b[0].writeln(": @", &b[0]);

Daha sonradan farkettiğin gibi, her gösterge bir dizi gibi kullanılabilir. (D'nin C kodlarını olduğu gibi kullanabilme isteklerinden birisinin etkisi.) Burada şanssız biçimde üye de dizi olunca kafamız karışıyor. Halbuki dizi gibi kullanılan, b'nin kendisidir. Şu program açıklayıcı olabilir:

import std.stdio;
import core.stdc.stdlib;

struct S {
  int i;
}

void main() {
  enum n = 10;

  // Birden fazla S için yer ayırıyoruz.
  // Bunun yerine calloc() vs. de kullanabilirdik.
  // (Not malloc belleği sıfırlamaz. İçinde çök değerler
  // görebiliriz.)
  auto v = malloc(n * S.sizeof);

  // malloc void* döndürür:
  static assert (is (typeof(v) == void*));

  // O bellek alanını S'ler için kullanmak için cast:
  auto ptr = cast(S*)v;

  // Şimdi bizim tür:
  static assert (is (typeof(ptr) == S*));

  // Ve bir C dizisi gibi kullanılabilir:
  // Dikkat: Buradaki örnekte çöp değerlerin
  // üzerine S atamakta bir tehlike yok ama
  // daha karmaşık türlerde program göçecektir
  // çünkü atama işlemi iki adımdan oluşur:
  // eski üyeleri sonlandır ve yeni üyelere
  // yeni değerler ver. (Eski nesneler çöp
  // değerlerle sonlandırılırken göçecektir.
  // (Burada değil, başka programlarda.))
  ptr[n / 2] = S(1_111_111_111);

  // Ve bir D dizisine dönüştürülebilir. (Çok
  // kullanışlı bir söz dizimi.)
  auto dizi = ptr[0..n];

  static assert (is (typeof(dizi) == S[]));

  writeln(dizi);
}

Ali

May 24
On 5/24/22 06:42, Ali Çehreli wrote:

>    // Şimdi bizim tür:
>    static assert (is (typeof(ptr) == S*));
>
>    // Ve bir C dizisi gibi kullanılabilir:

Şurada geçiyor:

  http://ddili.org/ders/d/gostergeler.html#ix_gostergeler.[]

>    // [...] (Eski nesneler çöp
>    // değerlerle sonlandırılırken göçecektir.

Öyle olmaması için emplace kullanabilirdim:

  http://ddili.org/ders/d/bellek_yonetimi.html#ix_bellek_yonetimi.emplace

Ali

May 24
On 5/24/22 06:52, Ali Çehreli wrote:

>    http://ddili.org/ders/d/gostergeler.html#ix_gostergeler.[]

Düzeltmeye çalışıyorum:

  <http://ddili.org/ders/d/gostergeler.html#ix_gostergeler.[]>

Eğer o da olmazsa o sayfada "Dizi erişim işleci [] ile kullanımı" başlığını arayabilirsiniz. :)

Ali

May 25
On Tuesday, 24 May 2022 at 13:42:44 UTC, Ali Çehreli wrote:
> Daha sonradan farkettiğin gibi, her gösterge bir dizi gibi kullanılabilir. (D'nin C kodlarını olduğu gibi kullanabilme isteklerinden birisinin etkisi.) [...]

Yani C'de de böyle, diziden farklı olarak göstergelerde köşeli parantez kullanımı var mı?

Teşekkürler...
May 24
On 5/24/22 21:50, Salih Dincer wrote:
> On Tuesday, 24 May 2022 at 13:42:44 UTC, Ali Çehreli wrote:
>> Daha sonradan farkettiğin gibi, her gösterge bir dizi gibi
>> kullanılabilir. (D'nin C kodlarını olduğu gibi kullanabilme
>> isteklerinden birisinin etkisi.) [...]
>
> Yani C'de de böyle, diziden farklı olarak göstergelerde köşeli parantez
> kullanımı var mı?

Evet ve aslında dizi[i] kullanımı, C'den beri perde arkasında aşağıdaki kullanımın aynısıdır:

  *(dizi + i)

Burada hatırlatmak gerek: Gösterge aritmetiğine göre, i eklemek, "i adet eleman öteyi göstermek" anlamına gelir, "i bayt öteyi" değil.

Ali

May 26

On Tuesday, 24 May 2022 at 13:42:44 UTC, Ali Çehreli wrote:

>

On 5/23/22 22:26, Salih Dincer wrote:
[...] Şu program açıklayıcı olabilir:

import std.stdio;
import core.stdc.stdlib;

struct S {
int i;
}
[...]

Hocam D'nin gözünü seveyim bea! Kodu C'de yazayım dedim o tutorial senin burdaki benim uğraştım durdum 😀

Neyse, bu örnek çok iyi oldu. Neticede bilgilerimizi tazeledik. Hele ki bunca seneden sonra, devamının olduğunu bildiğimiz bir işaretçi üzerinde, sanki bir diziymiş gibi kullanılabildiğini öğrenmek güzeldi.

Ben de D özelliği zannediyordum, teşekkürler...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct S {
  int8_t id;
  char name[6]; // 5 + 1(\0)
};

const int CITY = 35;

int main()
{
  int n = 0;
  struct S s, *ptr;
  ptr = (struct S*) malloc(CITY * sizeof(struct S));

  printf("ilk adresi: %p\n", ptr); // 0x55aca99ec260
  for(int i = 0; i < CITY; ++i)
  {
    ptr[i].id = i + 1;
  }
  printf("plaka kodu: %d\n", ptr[n].id);
  strcpy(ptr[n].name, "adana");
  printf("ilin ismi : %s\n", ptr[n].name);

  n = CITY - 1;

  printf("plaka kodu: %d\n", ptr[n].id);
  strcpy(ptr[n].name, "izmir");
  printf("ilin ismi : %s\n", ptr[n].name);

  for(int i = 0; i < CITY; ++i)
  {
    printf("%d: %s\n", ptr[i].id, ptr[i].name);
  }
  printf("son adresi: %p\n", &ptr[n]); // 0x55aca99ec34e
/* Son adresinden (...34e) ilk adresi (...260)'ı çıkarınca
 * 0xEE kalıyor ki bu onluk 238 demek ve bunu 34'e bölünce 7
 * değeri bulunuyor. Yani S yapısı 1 + 6 baytdan oluşuyor.
 */

  s = ptr[0];
  ptr[0].id = 0;
  printf("%s'nın plaka kodu: %d\n", s.name, s.id);

  return 0;
} /* ÇIKTISI:
ilk adresi: 0x55aca99ec260
plaka kodu: 1
ilin ismi : adana
plaka kodu: 35
ilin ismi : izmir
1: adana
2:
3:
...
35: izmir
son adresi: 0x55aca99ec34e
adana'nın plaka kodu: 1
*/