Linked Lists (Bağlı listeler), uygulanması için pointer (işaretçi) kullanan dinamik veri yapısının en iyi ve en basit örneğidir ve yazılım dünyasında önemli yeri olan veri yapılarından biridir. Dizilerde olduğu başta kaç tane elemanın olduğunu belirtmek gerekmemektedir. Dizilerde yapılan eleman ekleme, silme işlemleri ve araya eleman ekleme işlemleri yapılabilir. 

Ancak, pointer'ları anlamak linked list nasıl çalıştığını anlamak için çok önemlidir. Pointer konusu ile ilgili kafanızda soru işaretleri varsa pointer ile ilgili yazımızı inceleyebilirsiniz. 


Linked list'ler, dizideki herhangi bir noktadan gerektiği büyüyüp küçülebilen bir dizi işlevi görür.

Linked list'lerin dizilere göre bazı avantajları vardır:

1- Dizilerde eleman ekleme, silme gibi işlemler linked list'lere göre performans açısından daha maliyetlidir. Linked list'lerde ise bu işlem sadece basit bir pointer işlemi ile yapılır ve kaydırma işlemlerine ihtiyaç kalmaz. Bu sayede performanstan kazanç sağlanır. 

2- Linked list'ler dinamik veri yapılarıdır. Dizi tanımlaması yapılırken en başta veri boyutunu belirtmemiz gerekirken, linked list'lerde ise bu boyutu eleman ekleme ile artırabilir, eleman silme işlemleri ile boyutu küçültebiliriz.

Linked list'lerin dezavantajları:

1- Rastgele erişim yoktur. Dizideki n'inci öğeye, o öğeye kadar tüm öğeler üzerinde yineleme yapılmadan ulaşmak imkansızdır. Bu, listenin en başından başlamamız ve istenen öğeye ulaşana kadar listede kaç kez ilerlediğinizi saymanız gerektiği anlamına gelir. 

2- Linked list'ler sadece veriyi değil, veri ile birlikte bir sonraki düğüme işaret eden pointer'ları da tuttuğu için dizilere göre hafızada daha fazla yer kaplar


Linked List (Bağlı Listeler) Nedir?


Bağlı liste, her node (düğüm) bir değer ve bir işaretçi içeren, dinamik olarak ayrılmış düğümler kümesidir. Pointer her zaman listenin bir sonraki üyesini işaret eder. Pointer NULL ise, listedeki son düğümdür. 



Kısaca şöyle diyebiliriz; bağlı liste içerisinde bellek üzerinde tanımlanan elemanlar pointer yardımı ile birbirini takıp eden vagonlar gibi çalışır. Kendinden sonraki gelecek olan düğümün adresini tutar. Bu sayede, her düğüm kendinden sonraki gelecek olan düğümün yerini bilir. Bu özellikleri sayesinde, bellekte sıralanış şekli açısından esneklik sağlar.

Linked List Türleri


Simple Linked List: Bu tür linked list'de, listeyi yalnızca bir yönde hareket edebilir veya hareket ettirebilirsiniz.

Doubly Linked List: Bu tür linked list'de, listeyi her iki yönde de hareket ettirebilir veya çaprazlanabilir(ileri ve geri).

Circular Linked List: Bu tür linked list'de, bağlantılı listenin son düğümü, bir sonraki işaretçisinde bağlantılı listenin ilk/baş düğümünün bağlantısını içerir ve ilk/baş düğüm, bağlı listenin son düğümünün bağlantısını kendi içinde içerir. 

Linked List'lerin Temsili


Linked list, linked list'in ilk düğümüne bir işaretçi ile temsil edilir. İlk düğüm, linked list'in başı olarak adlandırılır. Linked list boşsa, başlığın değeri NULL'u gösterir.

Listedeki her düğüm en az iki bölümden oluşur:
  • Bir veri öğesi(tamsayı, diziler veya herhangi bir veri türü).
  • Bir sonraki düğüme işaretçi(veya referans)(bu düğümü diğerine bağlar) veya başka bir düğüm adresi.
C'de yapıları(structures) kullanarak bir düğümü temsil edebiliriz. Aşağıda tamsayı verileriyle bağlantılı bir liste düğümü örneği verilmiştir.

// bir linked list düğümü
struct Node{
int data;
struct Node* next;
};
3 düğümlü basit bit linked list'in oluşturulması:

#include <stdio.h>
#include <stdlib.h>
// bir linked list düğümü
struct Node{
int data;
struct Node* next;
};


int main() {
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;

// yığında 3 düğüm ayırmak
head = (struct Node*) malloc(sizeof (struct Node));
second = (struct Node*) malloc(sizeof (struct Node));
third =(struct Node*) malloc(sizeof (struct Node));

/* dinamik olarak 3 blok tahsis edilmiştir
* Bu üç bloğa head, second ve third olarak işaretçilerimiz var
*
head second third
| | |
| | |
+---+-----+ +----+----+ +----+----+
| # | # | | # | # | | # | # |
+---+-----+ +----+----+ +----+----+
Herhangi bir rastgele değeri temsil eder.
Veriler rastgele çünkü henüz bir şey atamadık.
*/

head->data = 1; // ilk düğüme değer atandı
head->next =second; // ilk düğümü, ikinci düğüme bağladık

/* veriler, ilk bloğun data kısmına atanmıştır.
* ve bloğun sonraki işaretçisi ikinciyi gösterir.
* yani ikisi de bağlı
head second third
| | |
| | |
+---+---+ +----+----+ +-----+----+
| 1 | o----->| # | # | | # | # |
+---+---+ +----+----+ +-----+----+
*/

second->data = 2; // ikinci düğüme değer atandı
second->next = third; // ikinci düğümü, üçüncü düğüme bağladık

/* veriler, ikinci bloğun data kısmına atanmıştır.
* ve ikinci bloğun bir işaretçisi üçüncü bloğa işaret eder.
* yani üç blok da birbirine bağlı.

head second third
| | |
| | |
+---+---+ +---+---+ +----+----+
| 1 | o----->| 2 | o-----> | # | # |
+---+---+ +---+---+ +----+----+
*/

third->data =3; // üçüncü düğüme değer atandı
third->next = NULL;

/* veriler, üçüncü bloğun data kısmına atanmıştır.
* ve üçüncü bloğun bir sonraki işaretçisi,
* linked list'in burada bittiğini belirtmek için NULL yapılır.
*
* Linked list'imiz hazır
head
|
|
+---+---+ +---+---+ +----+------+
| 1 | o----->| 2 | o-----> | 3 | NULL |
+---+---+ +---+---+ +----+------+

Tüm listeye temsil ulaşmak için yalnızca head'in yeterli olduğunu unutmayın.

*/
return 0;
}

Şimdi oluşturduğumuz listeyi dolaşalım ve her düğümün verilerini ekrana yazdıralım. Geçişler için ve düğüm verilerini yazdıran genel amaçlı bir printList() fonksiyonu yazalım.

#include <stdio.h>
#include <stdlib.h>
// bir linked list düğümü
struct Node{
int data;
struct Node* next;
};

// bu fonksiyon, verilen düğümden başlayarak linked list'in içeriğini yazdırır
void printList(struct Node* n){
while(n != NULL){
printf(" %d",n->data);
n = n->next;
}
}

int main() {
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;

// yığında 3 düğüm ayırmak
head = (struct Node*) malloc(sizeof (struct Node));
second = (struct Node*) malloc(sizeof (struct Node));
third =(struct Node*) malloc(sizeof (struct Node));

head->data = 1; // ilk düğüme değer atandı
head->next =second; // ilk düğümü, ikinci düğüme bağladık

second->data = 2; // ikinci düğüme değer atandı
second->next = third; // ikinci düğümü, üçüncü düğüme bağladık

third->data =3; // üçüncü düğüme değer atandı
third->next = NULL;

// fonksiyonu çağıralım
printList(head);

return 0;
}

Çıktı:

 1 2 3



C programlama ile ilgili olan diğer konulara aşağıdaki linkten ulaşabilirsiniz:


Kaynaklar:

https://www.learn-c.org/en/Linked_lists
programiz.com/dsa/linked-list
https://www.edureka.co/blog/linked-list-n-c/
https://www.geeksforgeeks.org/linked-list-set-1-introduction/
https://www.studytonight.com/data-structures/linked-list-vs-array

 
Bilgisayar içerisinde tüm veriler bitler ile temsil edilir. Her bit yalnızca 0 veya 1 değerini alabilir. Çoğu sistemde 8 bit bir baytı oluşturur. Byte, char tipi için standart depolama birimidir. Diğer veri tipleri daha çok sayıda baytlar içinde saklanır. Bit operatörleri operandlarının bitlerini yönetmek için kullanılır. Bit operatörleriyle genellikle işaretsiz tamsayılar (unsigned int) kullanılır. Bit işlemleri doğası gereği makine-bağımlı olduğundan dolayı bu programlar sizin sisteminizde doğru olarak çalışmayabilir.

Bit operatörleri şunlardır: AND(&), OR( | ), EXCLUSIVE OR(^), sola kaydırma(<<), sağa kaydırma(>>) ve tümleyen(~).

AND(&): İki operandın ikisinin de ilgili bitlerinde 1 varsa sonuçtaki bitler 1 yapılır.

OR( | ): İki operandın ilgili bitlerinden en az biri 1 ise sonuçtaki bitler 1 yapılır.

EXCLUSI ve OR (^): Operandların ilgili bitlerinden yalnızca biri 1 ise sonuçtaki bitler 1 yapılır.

Sola kaydırma (<<): İlk operandındaki bitleri ikinci operandında belirtilen sayı kadar sola kaydırır. Sağdan itibaren 0 ile doldurulur.

Sağa kaydırma(>>): İlk operandındaki bitleri ikinci operandında belirtilen sayı kadar sağa kaydırır. Soldan itibaren yapılacak doldurma işlemciye bağlıdır.

Tümleyen (~): Tüm sıfır bitleri 1, tüm 1 bitleri 0 yapar

İşaretsiz (unsigned) Tam Sayıyı Bit olarak Yazdırma

Bit operatörlerini kullanırken, değerleri ikilik sistemde yazdırmak bu operatörlerin etkilerini gösterebilmek için oldukça kullanışlıdır.

Aşağıdaki örnek, unsigned bir tam sayıyı her biri 8 bitten oluşan gruplarla ikilik gösterimde yazdırmaktadır.

#include <stdio.h>

void displayBits(unsigned int value);

int main(){
unsigned int x;
printf("%s","Enter a nonnegative int: ");
scanf("%u",&x);
displayBits(x);
}

void displayBits(unsigned int value){
unsigned int c; // sayıcı

//displayMask'ı tanımlama ve 31 biti solo kaydırma
unsigned int displayMask = 1 << 31;

printf("%10u = ",value);
for(c=1;c<=32;++c){
putchar(value & displayMask ? '1' : '0');
value <<=1; // 1 ile değeri sola kaydırma

if(c % 8 == 0) { // 8 bitten sonraki yerin çıkışı
putchar(' ');
}
}
putchar('\n');
}
Ekran Çıktısı:

Enter a nonnegative int:65000
      65000 = 00000000 00000000 11111101 11101000

displayBits fonksiyonu value ve displayMask değişkenlerini birleştirmek için bit AND operatörünü kullanır. Sıklıkla bit AND operatörü maske (belirli bitleri 1 değerine ayarlanmış bir tam sayı değeri) adı verilen bir operant kullanılır. Maskeler diğer bitleri seçerken bazı bitleri değer içinde saklamak için kullanılır. displayBits fonksiyonunda maske değişkeni displayMask şu değere atanmıştır;

1 << 31 (10000000 00000000 00000000 00000000)

Sola kaydırma operatörü, 1 değerini displayMask içindeki en düşük değerlikli (en sağdaki) bitten en yüksek değerlikli (en soldaki) bite doğru kaydırır ve sağdan itibaren bitleri o ile doldurur.
putchar(value & displayMask ? '1' : '0');

değişkenin en solundaki bit değerinin 0 ya da 1 olarak çıkarılmasına karar verir. value ve displayMask "&" kullanılarak birleştirilirse value değişkeninde en soldaki bit dışındaki bitler saklanır çünkü 0 ile biten bitler birbirine geçiş sağlar. Eğer en soldaki bit 1 ise value ve displayMask gerçek bir değer alır ve 1 ekrana yazılır aksi durumda 0 yazılır. Ardından value değişkeni bir sola kaydırılır value <<=1 ile. Atanmamış değişken value'da bu adımlar her bit için tekrarlanır .

Bitsel AND Operatörü (&)


Kullanılan iki operandın bitleri 1 ise, bitsel AND'in çıkışı 1'dir. Operandlardan herhangi biri 0 ise, bitsel AND'in çıkışı 0'dır.

12 ve 25 tamsayılarının bit düzeyinde AND işlemini inceleyelim:

12 = 00001100 (In Binary)
25 = 00011001 (In Binary)

Bit Operation of 12 and 25
  00001100
& 00011001
  ________
  00001000  = 8 (In decimal)
Örnek:

#include <stdio.h>
int main() {
    int a = 12, b = 25;
    printf("Output = %d", a&b);
    return 0;
}

Çıktı:

Output = 8

Bitsel OR Operatörü (|)


Kullanılan operadlardan en az biri 1 ise, bitsel Or'ın çıkışı 1'dir.

12 = 00001100 (In Binary)
25 = 00011001 (In Binary)

Bitwise OR Operation of 12 and 25
  00001100
| 00011001
  ________
  00011101  = 29 (In decimal)
Örnek:

#include <stdio.h>
int main() {
    int a = 12, b = 25;
    printf("Output = %d", a|b);
    return 0;
}


Çıktı:

Output = 29

Bitsel XOR (exclusive OR) Operatörü (^)


İki operandaki bitler zır ise, bitrsel XOR'un çıkışı 1 olur.

12 = 00001100 (In Binary)
25 = 00011001 (In Binary)

Bitwise XOR Operation of 12 and 25
  00001100
^ 00011001
  ________
  00010101  = 21 (In decimal)
Örnek:

#include <stdio.h>
int main() {
    int a = 12, b = 25;
    printf("Output = %d", a^b);
    return 0;
}

Çıktı:

Output = 21


Shift Operatörleri


C'de iki tane shift operatörü vardır: Right shift ve left shift


Rigth Shift Operatörü(>>)


Sağa kaydırma operatörü, tüm bitleri belirli sayıda belirtilen bit kadar sağa kaydırır. 

212 = 11010100 (In binary)
212>>2 = 00110101 (In binary) [Right shift by two bits]
212>>7 = 00000001 (In binary)
212>>8 = 00000000 
212>>0 = 11010100 (No Shift)

Left Shift Opetatörü(<<)


Sola kaydırma operatörü, tüm bitleri belirli sayıda belirtilen bit kadar sola kaydırır. Sola kaydırma operatörü tarafından boşaltılan bit konumları 0 ile doldurulur.
212 = 11010100 (In binary)
212<<1 = 110101000 (In binary) [Left shift by one bit]
212<<0 = 11010100 (Shift by 0)
212<<4 = 110101000000 (In binary) =3392(In decimal)
Örnek

#include <stdio.h>
int main() {
    int num=212, i;
    for (i=0; i<=2; ++i) {
        printf("Right shift by %d: %d\n", i, num>>I);
    }
    printf("\n");

    for (i=0; i<=2; ++i) {
        printf("Left shift by %d: %d\n", i, num<<i);    
    }

    return 0;
}

Çıktı:



Right Shift by 0: 212
Right Shift by 1: 106
Right Shift by 2: 53

Left Shift by 0: 212
Left Shift by 1: 424
Left Shift by 2: 848




C programlama ile ilgili olan diğer konulara aşağıdaki linkten ulaşabilirsiniz:


Kaynaklar:
https://www.bilgigunlugum.net/prog/cprog/2c_veri
https://www.programmingsimplified.com/c/source-code/c-program-convert-decimal-to-binary
https://www.programiz.com/c-programming/bitwise-operators
https://www.javatpoint.com/bitwise-operator-in-c
Deitel Deitel C/C++



Birlikler, aynı bellek anını paylaşan üyelere sahiptir ve yapılar gibi türetilmiş veri tipidir. Bir programda farklı durumlar için bazı değişkenler birbiri ile ilgili değildir fakat diğer değişkenler birbiri ile ilgili olabilir. Bundan dolayı birlikler kullanılmayan değişkenlerin boşu boşuna hafıza kullanımını önlemek için aynı hafıza alanını paylaşır. Birlik üyeleri herhangi bir tip olabilir. Union'da saklanacak byte miktarı, en az birliğin büyük hafıza alanı isteyen üyesini alacak şekilde olmalıdır. Çoğu durumda union'lar iki veya daha fazla veri tipi içerir. Kullanımda, sadece bir üye ve böylece bir veri tipi referans olarak kullanılabilir.


Union/Birlik Bildirimi

Birliklerin bildirimi de yapılarda olduğu gibidir. Yalnızca struct anahtar sözcüğü yerine union anahtar sözcüğü kullanılır.

union [birlik_ismi] {
    <tür> <birlik_elemanı>; 
    <tür> <birlik_elemanı>; 
    <tür> <birlik_elemanı>; 
    ...
}

Yukarıdaki genel biçimde:

union :                 Bildirim için gerekli bir anahtar sözcüktür.
birlik_ismi :         Birliği anlatan isimlendirme kurallarına uygun herhangi bir isim olabilir.
birlik_elemanı :   Birlik elemanıdır; isimlendirme kurallarına uygun herhangi bir isim olabilir.


Örnek:
union number {
int x;
double y;
};

Union/Birlik Değişkenlerinin Tanımlanması

Tıpkı yapılarda olduğu gibi birliklerde de yer ayırma işlemi bildirim ile değil tanımlanma işlemi ile yapılmaktadır. Birlik bildirimlerinin yapı bildirimlerinde tek farkı struct anahtar sözcüğü yerine union anahtar sözcüğü kullanılmasıdır. 

Genel biçimi:

union <birlik_ismi> <birlik_değişkeninin_ismi>;

Örneğin;
union number {
int x;
double y;
}a,b;
veya

union number a,b;

Örnekler

1) union ve struct arasındaki fark
#include <stdio.h>
union unionJob
{
//defining a union
char name[32];
float salary;
int workerNo;
} uJob;

struct structJob
{
char name[32];
float salary;
int workerNo;
} sJob;

int main()
{
printf("size of union = %d bytes", sizeof(uJob));
printf("\nsize of structure = %d bytes", sizeof(sJob));
return 0;
}
Ekran Çıktısı:

size of union = 32 bytes
size of structure = 40 bytes

2)
#include <stdio.h>
#include <string.h>

union Data {
int i;
float f;
char str[20];
};

int main( ) {

union Data data;

printf( "Memory size occupied by data : %d\n", sizeof(data));

return 0;
}

Ekran Çıktısı:

Memory size occupied by data : 20

3)
#include <stdio.h>
#include <string.h>

union Data {
int i;
float f;
char str[20];
};

int main( ) {

union Data data;

data.i = 10;
data.f = 220.5;
strcpy( data.str, "C Programming");

printf( "data.i : %d\n", data.i);
printf( "data.f : %f\n", data.f);
printf( "data.str : %s\n", data.str);

return 0;
}

Ekran Çıktısı:

data.i : 1917853763
data.f : 4122360580327794900000000000000.000000
data.str : C Programming

4)

#include <stdio.h>

// Declaration of union is same as structures
union test {
int x, y;
};

int main()
{
// A union variable t
union test t;

t.x = 2; // t.y also gets value 2
printf("After making x = 2:\n x = %d, y = %d\n\n",
t.x, t.y);

t.y = 10; // t.x is also updated to 10
printf("After making y = 10:\n x = %d, y = %d\n\n",
t.x, t.y);
return 0;
}
Ekran Çıktısı:

After making x = 2:
 x = 2, y = 2

After making y = 10:
 x = 10, y = 10

5)
#include <stdio.h>

union test {
int x;
char y;
};

int main()
{
union test p1;
p1.x = 65;

// p2 is a pointer to union p1
union test* p2 = &p1;

// Accessing union members using pointer
printf("%d %c", p2->x, p2->y);
return 0;
}
Ekran Çıktısı:

65 A


C programlama ile ilgili olan diğer konulara aşağıdaki linkten ulaşabilirsiniz:


Kaynaklar:
A'dan Z'ye C programlama
Deitel C/C++
https://www.tutorialspoint.com/cprogramming/c_unions.htm
https://www.programiz.com/c-programming/c-unions
https://www.geeksforgeeks.org/union-c/


 

Bu yazımızda, C programlamanın en önemli elemanlarında bir olan yapılar (struct) konusuna değineceğiz. 



Yapı (Struct) Nedir ?

Yapılar -bazen topluluklar diye anılır- tek bir isim altında onunla ilgili değişkenlerin olduğu koleksiyonlardır. Yapılar, sadece aynı veri türünde öğeleri içeren dizilerin aksine farklı veri türünde değişkenler içerebilir. Yapılar, diziler gibi belleğe sürekli biçimde yerleşen nesnelerdir. Dizilerde olduğu gibi başlangıç adresleri içerilerek fonksiyonlara kolaylıkla aktarılabilirler. 

Yapıların Bildirimi

Yapılar türetilmiş veri türleridir. Yapılar diğer türdeki nesneleri kullanarak inşa edilirler. Yapı bildiriminin genel biçimi:

struct [yapı_ismi] {
    <tür> <yapı_elemanı>;
    <tür> <yapı_elemanı>;
    <tür> <yapı_elemanı>;
    ...
};


Yukarıdaki genel biçimde:

struct :             Bildirim için gerekli anahtar sözcüktür.
yapı_ismi :      Yapıyı anlatan isimlendirme kurallarına uygun herhangi bir isim olabilir. / yapı                                         etiketidir.
yapı_elemanı : Yapıyı oluşturan değişken isimleridir; isimlendirme kurallarına uygun herhangi bir isim                           olabilir.

!! Bildirimin küme parantezinden sonra noktalı virgül ile sonlandırıldığına dikkat ediniz.!!

Örneğin, düzlemde bir nokta x ve y bileşenlerinden oluştuğuna göre, bu aynı elemanlar yerine bir yapı biçiminde de bildirebiliriz:

struct NOKTA {
    int x;
    int y;
};
...


Benzer biçimde, tarih bilgileri de hiçbiri int türünden üç ayrı değişken yerine, yapı kullanılarak mantıksal bir bütünlük içinde ifade edilebilir:

struct DATE {
    int day;
    int month;
    int year;
};

Yukarıdaki bildirimde DATE yapının ismi; day, month ve year ise int türünden yapı elemanlarıdır.

Yapı bildirimiyle derleyici yalnızca yapılar hakkında bilgi edinir; bellekte onlar için herhangi bir yer ayrılmaz. Yapı bildirimlerini bir çeşit şablon tanımlaması gibi düşünebilirsiniz. Tıpkı fonksiyon prototiplerinde olduğu gibi yapı bildirimleri de yalnızca derleyiciyi bilgilendirmek amacıyla kullanılmaktadır.

Yapı Değişkenlerinin Tanımlanması

Bellekte yer ayırma işlemi yapı değişkenlerinin tanımlanmasıyla oluşur. Yapı değişkenlerinin tanımlanması aşağıdaki iki biçimde yapılır:

struct <yapı_ismi> <yapı_değişkeninin_ismi>;

veya

struct [yapı_ismi] {
    ...
} [değişken_listesi];

Yağı değişkenlerinin yapı bildiriminde sonra tanımlanması zorunludur. 

Örneğin:

struct NOKTA {
    int x;
    int y;
};
...

struct NOKTA a;

veya

struct NOKTA {
    int x;
    int y;
}a;
...


benzer biçimde DATE yapısı türünden bir d değişkeni:

struct DATE {
    int day;
    int month;
    int year;
};
...
struct DATE d;

veya

struct DATE {
    int day;
    int month;
    int year;
}d;
...

Yapı Değişkenlerine İlk Değerin Verilmesi

Yapı değişkenlerine dizilerde olduğu gibi küme parantezleri içerisinde ilk değer verilir. 

Örneğin:

struct date {
    int day;
    int month;
    int year;
};
...
struct date d = {1,4,1995};


Derleyici ilk değerleri yapı elemanlarına sırasıyla yerleştirir. Yani yukarıdaki örnekte yapı elemanlarının alacağı değerler şöyledir:

d.day => 1
d.month => 4
d.year => 1995


Yapı Üyelerine Erişim

Yapı üyelerine erişmek için iki operatör kullanılır: Yapı üyesi operatörü (.) (aynı
zamanda nokta operatörü olarak da bilinir) ve yapı işaretçisi operatörü ( ->) (aynı zamanda ok
operatörü olarak da adlandırılır). Yapı üyesi operatörü yapının değişken ismiyle yapı üyesine erişir. 

Örneğin:

printf("%d",d.day);

Yapı işaretçisi operatörü -aralarında herhangi bir boşluk olmayan eksi (-) işareti ve büyüktür (>) işaretinden oluşan - yapıda bir işaretçi üzerinden bir yapı üyesine erişir.

struct data *x;
printf("%d", x-> year);

Örnek:

#include <stdio.h>

struct card {
char *face;
char *suit;
};

int main( )
{
struct card aCard;
struct card *cardPtr;

aCard.face = "Ace";
aCard.suit = "Spades";

cardPtr = &aCard;

printf( "%s%s%s\n%s%s%s\n%s%s%s\n", aCard.face," of ", aCard.suit,
cardPtr->face," of ",cardPtr->suit,
(*cardPtr).face," of ",(*cardPtr).suit);
return 0;
}
Ekran Çıktısı:

Ace of Spades
Ace of Spades
Ace of Spades

İç İçe Yapılar

Bir yapının içende başka bir yapı nesnesi tanımlanabilir. İç içe yapıların tanımlanması C'de iki biçimde yapılmaktadır:

1) İçerideki yapının bildirimini daha yukarıda yaparak. Bu durumda derleyici doğal akış yönünde ilerlerken bildirilen yapıyı tanıyabilir.

struct date{
    int day, month, year;
};
...
struct person {
    char name[30];
    struct date bday;
};

2) İçerideli yapının dışındaki yapının içerisinde bildirilmesiyle. Bu durumda değişken tanımlanması da yapılmalıdır:

struct person {
    char name[30];
    struct date{
        int day, month, year;
    }bday;
};

Yapıların Fonksiyonlara Parametre Olarak Geçirilmesi

C'de parametrelerin kopyalanarak fonksiyonlara geçirildiğini hatırlayalım. Yapı değişkenleri de fonksiyonlara kopyalanarak parametre olarak geçirilebilirler. 

Örnek:

#include <stdio.h>

struct date{
int day,month,year;
};

void dispDate(struct date x){
printf("Year: %d\n",x.year);
printf("Month: %d\n",x.month);
printf("Dat: %d\n",x.day);
}

int main() {
// Write C code here
struct date n;

n.day = 4;
n.month = 5;
n.year = 1995;
dispDate(n);

}
Ekran Çıktısı:

Year: 1995
Month: 5
Dat: 4




C programlama ile ilgili olan diğer konulara aşağıdaki linkten ulaşabilirsiniz: