Bir dizi tek tipten çok değer tutar. Bir struct bunun tersini yapar: farklı tiplerden birkaç değer tutar ve onlara tek bir şey gibi davranır. Bir nokta bir x ve bir y'dir. Bir çalışan bir isim, bir kimlik ve bir maaştır. Yapılar olmadan bunları üç ayrı değişken olarak taşır ve kimin maaşının kime ait olduğunu hiç karıştırmadığınızı umardınız.
Bir Yapı Tipi Bildirmek
Bir yapı bildirimi bir etiket adlandırır ve üyeleri süslü parantez içinde listeler:
struct Point {
int x;
int y;
};
Kapanış parantezinden sonraki noktalı virgül zorunludur - onu unutmak, bir C acemisinin karşılaşacağı en kafa karıştırıcı hata mesajlarından biridir, çünkü derleyici sonraki satırı suçlar.
Bu bir değişken değil bir tip bildirir. C'de tipin tam adı, anahtar kelime dahil, struct Point'tir:
Üyeler nokta operatörüyle, p.x, okunur ve yazılır. Bir yapı değişkeni sıradan bir değişkendir: yığında yaşar, = ile aynı tipten başka bir yapıya atanabilir ve kapsamının sonunda yok olur.
Her yerde struct Point yazmak yorucu olur; neredeyse tüm gerçek C kodunun bildirimi bir typedef ile sarmasının ve tipin yalnızca Point olmasının sebebi budur.
Bir Yapıya İlk Değer Vermek
Bir yapıyı bildirdiğiniz anda doldurabilirsiniz. Konumsal biçim değerleri bildirim sırasına göre listeler:
struct Point p = {3, 4}; // x = 3, y = 4
Belirtilmiş ilk değer bunun yerine her üyeyi adlandırır ki bu daha anlaşılır ve daha güvenlidir:
Dikkate değer üç şey:
- Belirtilmiş biçim üyeleri herhangi bir sırada listeleyebilir, dolayısıyla sonradan bir üye eklemek ya da yeniden sıralamak değerleri sessizce yanlış yuvalara kaydırmaz.
- Dışarıda bıraktığınız her üyeye sıfır atanır -
{0}, bütün bir yapıyı sıfırlamanın deyimsel yoludur. char name[32]üyesi yapının içindeki gerçek bir dizidir, dolayısıyla metin başka bir yerde değil yapının kendisinde saklanır. Bu ayrıca sonradana.name = "Ada";'nın geçersiz olduğu anlamına gelir;strcpy'ye ihtiyacınız var (bkz. metin fonksiyonları).
İlk değeri olmayan bir yapı ilk değersizdir ve üyelerini yazmadan önce okumak tanımsız davranıştır. = {0} hiçbir şeye mal olmaz ve tüm hata kategorisini ortadan kaldırır.
Atamak ve Karşılaştırmak
Yapı ataması her üyeyi kopyalar:
a'ya dokunulmadı: b kendi kopyasını aldı. Ama C'nin size vermediği şeye dikkat edin - yapılar için == yoktur. if (a == b) derlenmez. Karşılaştırmak, üyeleri karşılaştırmak demektir:
if (a.x == b.x && a.y == b.y) { /* eşit */ }
Kısayol olarak memcmp'ye uzanmayın. Derleyiciler hizalama için üyeler arasına görünmez dolgu baytları ekler ve o baytlar çöp tutabilir, dolayısıyla üyeleri özdeş iki yapı bayt bayt eşitsiz karşılaştırılabilir.
Yapı Dizileri
Bir yapı diğerleri gibi bir tip olduğu için onlardan bir dizi yapabilirsiniz - bir kayıt tablosu tutmanın standart yolu.
staff[i].salary, "eleman i, sonra onun salary üyesi" diye okunur - indeksleme noktadan daha sıkı bağlanır, dolayısıyla parantez gerekmez.
Yapılar Fonksiyonlara Kopyalanır
İnsanları yakalayan kural budur. Bir fonksiyona yapı geçirdiğinizde C onu kopyalar. Fonksiyon kendi özel kopyası üzerinde çalışır:
p hâlâ (3, 4)'tür. distance_from_origin'in yaptığı gibi bir yapıyı değerle okumak gayet sorunsuzdur ve küçük yapılar için çoğu zaman en anlaşılır seçimdir. Ama fonksiyonun çağıranın yapısını değiştirmesi gerekiyorsa - ya da yapı, kopyalamanın israf olacağı kadar büyükse - bunun yerine bir gösterici geçirin. Bu, yapılar ve göstericiler sayfasının konusudur.
Bir yapıyı değerle döndürmek de aynı şekilde çalışır ve tamamen geçerlidir:
struct Point make_point(int x, int y) {
struct Point p = {x, y};
return p;
}
İç İçe Yapılar
Bir yapı üyesi kendisi bir yapı olabilir. İçeri ulaşmak için noktaları zincirleyin:
b.published.year her seferinde bir seviye içeri yürür. İç içe yerleştirme, C'de gerçek veri modellerini kurma yolunuzdur - ve içteki yapı dıştakinin içinde saklanır, gösterilmez, dolayısıyla tüm Book tek bir bitişik bellek bloğudur.
Boyut, Dolgu ve Üye Sırası
sizeof size bir yapının ne kadar büyük olduğunu söyler ve cevap çoğu zaman üyelerinin toplamından büyüktür:
Tipik bir makinede Wasteful 12 bayt ve Tidy 8 bayttır; her ikisi de aynı üç üyeyi tutmasına rağmen. Derleyici, her üye tipinin sevdiği bir adreste otursun diye dolgu ekler - bir int genellikle 4'ün katını ister. Büyük üyeleri küçüklerden önce gruplamak daha iyi paketleme eğilimindedir.
Bu nadiren önemlidir (bir milyon elemanlı bir dizi, bir ağ paketi düzeni) ve kendi kodunuzun doğruluğu için asla önemli değildir. Açıkladığı şey, sizeof'un sizi neden şaşırttığı ve yapılarda memcmp'nin neden kötü bir fikir olduğudur.
Sıkça Sorulan Sorular
C'de bir yapı nasıl bildirilir?
struct yazın, ardından bir etiket adı ve süslü parantez içinde üye listesi: struct Point { int x; int y; };. Bu bir değişken değil bir tip bildirir. Bir değişken yapmak için sonra struct Point p; yazarsınız - C'de struct kelimesi tip adının bir parçasıdır; kodun çoğunun onu bir typedef ile eşlemesinin sebebi budur.
Yapılar için . ile -> arasındaki fark nedir?
. ile -> arasındaki fark nedir?Yapının kendisine sahipken . (p.x), ona bir göstericiye sahipken -> (ptr->x) kullanın. Ok, (*ptr).x'in kısaltmasıdır. Ayrıntılar için bkz. yapılar ve göstericiler.
C'de yapılar değerle mi referansla mı geçirilir?
Her zaman değerle. Bir fonksiyona yapı geçirmek her üyeyi kopyalar, dolayısıyla fonksiyonun içindeki değişiklikler çağıranın değişkenini etkilemez. Özgünü değiştirmek - ya da büyük bir yapıyı kopyalamaktan kaçınmak - için bunun yerine bir gösterici geçirin.
C'de bir yapıya nasıl ilk değer veririm?
Ya konumsal olarak, struct Point p = {3, 4}; ya da belirtilmiş ilk değerlerle, struct Point p = {.y = 4, .x = 3};. Belirtilmiş biçim her üyeyi adlandırır, dolayısıyla birinin sonradan yapıyı yeniden sıralamasından sağ çıkar ve adlandırılmayan üyeleri sıfırlanmış bırakır.