Bir yapıyı 0 olarak başlatmak


116

Böyle bir yapım varsa:

typedef struct
{
    unsigned char c1;
    unsigned char c2;
} myStruct;

Bu yapıyı 0 olarak başlatmanın en kolay yolu ne olabilir? Aşağıdakiler yeterli olur mu?

myStruct _m1 = {0};

veya Her bir üyeyi açık bir şekilde 0 olarak başlatmam gerekir mi?

myStruct _m2 = {0,0};

Yanıtlar:


143

İlki en kolay olanıdır ( daha az yazmayı gerektirir ) ve çalışması garantilidir, tüm üyeler 0[Ref 1] olarak ayarlanacaktır .
İkincisi daha okunabilir.

Seçim, kullanıcı tercihine veya kodlama standardınızın gerektirdiği seçeneğe bağlıdır.

[Ref 1] Referans C99 Standardı 6.7.8.21:

Küme ayracı ile çevrili bir listede, bir toplamın öğeleri veya üyeleri olduğundan daha az sayıda başlatıcı varsa veya dizideki öğelerden, bilinen boyuttaki bir diziyi başlatmak için kullanılan bir dize değişmezinde daha az karakter varsa, toplamın geri kalanı Statik depolama süresine sahip nesnelerle aynı şekilde başlatılabilir.

İyi Okuma:
C ve C ++: Otomatik yapının kısmi başlatılması


9
Ayrıca kullanıyorum = {};Ancak bunun geçerli olup olmadığından emin değilim.
William Entriken

15
@FullDecent başlatma için boş küme ayracı bir GNU oluşumudur.
a3f

2
@ alias65536 Soru C ++ değil C olarak etiketlendi.
a3f

3
Bir hata aldım: "[-Werror = eksik-parantezler] başlatıcı etrafında eksik parantez" muhtemelen bir üye dizisi nedeniyle: /
DrumM

3
@Edenia. Katılmıyorum. Ne foo = {0}anlama geldiğini zaten biliyorum . Eğer foo = ZERO_FULLgörürsem, ZERO_FULL'un tanımı için grep yapmam gerekirdi.
Andrew Bainbridge

32

Veriler statik veya global bir değişkense, varsayılan olarak sıfır doldurulur, bu nedenle sadece beyan edin myStruct _m;

Veriler yerel bir değişkense veya yığın tahsisli bir bölgeyse, aşağıdaki memsetgibi temizleyin :

memset(&m, 0, sizeof(myStruct));

Mevcut derleyiciler (örn. Son sürümleri gcc) bunu pratikte oldukça iyi optimize eder. Bu, yalnızca tüm sıfır değerleri (boş işaretçiler ve kayan nokta sıfır dahil) tüm sıfır bitler olarak temsil edilirse çalışır, bu da bildiğim tüm platformlarda doğrudur (ancak C standardı bunun yanlış olduğu uygulamalara izin verir; Böyle bir uygulama bilmiyorum) .

Belki kodlayabilirsin myStruct m = {};veya myStruct m = {0};(ilk üyesi myStructskaler olmasa bile ).

Benim hissim, memsetyerel yapılar için kullanmanın en iyisi olduğu ve çalışma zamanında bir şeyin yapılması gerektiği gerçeğini daha iyi iletiyor (oysa genellikle, genel ve statik veriler, çalışma zamanında herhangi bir maliyet olmaksızın derleme zamanında başlatılmış olarak anlaşılabilir) .


7
Yapının tüm baytlarının 0tüm yapı üyelerini 0gerçi ile başlatmaya eşdeğer olacağının garantisi yoktur . Pek çok platformda bu doğru olacaktır, ancak evrensel olarak değil.
Sander De Dycker

1
Bir örnek paylaşır mısın Sander? Gerçek merak. (Açıkçası, anlamına gelmez evrensel doğru değil bir istisna to-açıklamak kolay, ama varsa var ...)
Steven Fisher

2
standart boş işaretçisi izin (veya sıfır kayan nokta sayısı) hepsi sıfır bitten daha başka bir şey tarafından bellekte temsil edilmesi. Çok az ve tuhaf uygulama bunu yapıyor (hiçbirini isimlendiremem).
Basile Starynkevitch

-1, OP'nin çirkin hakkında sorduğu ilklendirmeyi bulabilirsiniz, ancak bu tam olarak standart tarafından öngörülen şeydir ve bu, tüm derleyiciler tarafından kolayca optimize edilebilir. Daha sonra, form {}geçerli C değil, yalnızca C ++ ile kullanılabilir.
Jens Gustedt

7
@Steven: Sadece belirsiz ve / veya eski platformları düşünebiliyorum. C SSS, NULLtamamı 0bit olmayan bir göstericiye sahip platformların bir listesine sahiptir : c-faq.com/null/machexamp.html . Ve sonra, platformun kayan nokta değerlerini temsil etmek için IEEE 754 kullanmama olasılığı var, ancak tamamen 0bit 0.0değerine sahip olmayan başka bir temsil kullanıyor - ama kuşkusuz böyle bir platform bilmiyorum.
Sander De Dycker

19

Bkz. §6.7.9 Başlatma:

21 Küme ayracı içine alınmış bir listede, bir kümenin öğeleri veya üyeleri olduğundan daha az sayıda başlatıcı varsa veya dizideki öğelerden, bilinen boyuttaki bir diziyi başlatmak için kullanılan bir dize değişmezinde daha az karakter varsa, toplamın geri kalanı Statik depolama süresi olan nesnelerle aynı şekilde başlatılmalıdır.

Yani, evet ikisi de çalışıyor. C99'da, belirlenmiş başlatma adı verilen yeni bir başlatma yönteminin de kullanılabileceğini unutmayın:

myStruct _m1 = {.c2 = 0, .c1 = 1};

En önemlisi, bu zaten C89: open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf#page=139 (Belirli sinyal işleme hedefleri için önemli)
Tobias
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.