sizeof style: sizeof (type) ya da sizeof değişkeni?


22

Bellekle sizeofilgili işlemler için kullanmanın iki stilini gördüm (örneğin memsetveya içinde malloc):

  • sizeof(type), ve
  • sizeof variable veya sizeof(variable)

Hangisini tercih edersiniz, ya da iki stilin bir karışımını kullanırdınız ve her bir stili ne zaman kullanırdınız? Her stilin artıları ve eksileri nelerdir ve bunları kullandığınızda?

Örnek olarak, bir stilin yardımcı olduğu ve diğerinin desteklemediği aşağıdaki durum çiftini görebiliyorum:

İşaretçi yönlendirmesini yanlış aldığınızda:

type *var;
...
memset(var, 0, sizeof var);    /* oops */

Tür değiştiğinde:

new_type var;    /* changed from old_type to new_type */
...
memset(&var, 0, sizeof(old_type));    /* oops */

Yanıtlar:


30

Ben perfer sizeof(variable)üzerinde sizeof(type). Düşünmek:

int a1;
float a2;
memset(&a1,0,sizeof(a1));
memset(&a2,0,sizeof(a2));

vs.

int a1;
float a2;
memset(&a1,0,sizeof(int));
memset(&a2,0,sizeof(float));

İlk durumda, doğru boyutların geçtiğini doğrulamak kolaydır memset. İkinci durumda, tutarlı olduğunuzdan emin olmak için üst ve alt bölümleri sürekli olarak gözden geçirmeniz gerekir.


4
Ayrıca, değişkenin türünü değiştirirseniz, türün değişmesi gerektiğini varsayan kod. Bence mümkün olduğu kadar az tipte bağımlılıkla doğru kodun kullanılması tercih edilir. (Büyük bir 16 - 32 bitlik dönüşüm projesinden geri döndüm.)
Robot Gort

Bu, bir typedef oluşturmanın yaygın olmadığı C dizileriyle çalışmak için tercih edilir, ancak char array [MAX_SIZE];
mattnz

@ vy32: Yanlış 1: "sizeof (dizi) dizinin boyutunu ... göstericinin boyutunu diziye döndürmez" - eğer arraygerçekten bir C dizisi ise, sizeof(array)dizi elemanlarını saklamak için gereken bayt sayısını döndürür. . Eğer arraybir çürümüş C dizinin ilk elemana bir gösterici, sonra ifadesi tutar. Bir C dizisini işlev bağımsız değişkeni olarak geçirmek, işlevdeki bir işaretçi gibi görünmesini sağlar - boyut olarak olduğu gibi bir dizi olduğunu ispatlayan tüm bilgiler kaybolur. Bu yüzden çürümüş . Yanlış 2: "C dizileri aslında yok; işaretçiler için basitçe sözdizimsel şeker."
Johann Gerell

9

Tercih (her zaman olduğu gibi) niyetinizi mümkün olduğunca doğrudan yansıtmaktır.

Mevcut bir değişkenin hafızasına karşı çalışmak niyetinde midir? Eğer öyleyse, o zaman bunu kullanın sizeof(variable), bu mümkün olduğu kadar yakından gösterir, bu sizin değer verdiğiniz değişkenin hafızasıdır.

Örneğin, yeni bir örnek için ne kadar bellek ayrılması gerektiğini belirlemek için tür üzerinde bir hesaplama yapmak niyetinde mi? Eğer öyleyse, o zaman kullanın sizeof(type).

Yani tercih ederim

struct foo *bar;
bar = (struct foo *) malloc(sizeof(struct foo));

üzerinde

bar = (struct foo *) malloc(sizeof(*bar));

İkinci durum , henüz var olmayan bir değişkene erişmeye çalıştığınız gibi görünüyor .

Öte yandan tercih ederim

char Buffer[256];
memset(Buffer, 0, sizeof(Buffer));

üzerinde

char Buffer[256];
memset(Buffer, 0, 256 * sizeof(char));

niyet açıkça değişkenin içeriğini sıfır doldurmak olduğundan, bu yüzden karşı koymamız gereken değişkendir. Meta veri türünü kullanmaya çalışmak burada bazı şeylerin kafasını karıştırır.



Her zaman yaparım, ama bu kişisel zevk meselesi. Bunu göz önünde void *ler otomatik olarak misfeature olmak diğer işaretçi türlerine alaşım olan'.
Aidan Cully

3

Ben büyük ölçüde tercih ediyorum sizeof(type)üzerinde sizeof variable. Sizi türü hakkında daha fazla endişe etmeye ve daha fazla değişiklik yapmaya zorlasa da, C'deki hataların en yaygın nedeni arasında yer alan işaretçi dolaylı hatalardan kaçınmanıza yardımcı olur .

sizeof(type)Türün değiştiği hatalar hakkında çok endişelenmem ; Ne zaman bir değişkenin tipini değiştirirseniz, o değişkenin nerede olduğunu ve herhangi bir sizeof(type)ifadeyi değiştirmeniz gerekip gerekmediğini görmek için hızlı bir tarama yapmanız gerekir . Her zaman bu yanlış anlama şansı olsa da, işaretçi dolaylı hatalardan çok daha düşük bir risk taşır.

Bunun bir avantajı sizeof variablediziler içindir, ancak pratikte dizileri birinci / len çiftler olarak geçirmenin çok daha yaygın olduğunu (bu durumda sadece uzunluğu kullanın), artı boyutu yanlış bulmaktan çok kolay olduğunu da buldum. Bu örnekte olduğu gibi dizi / işaretçi çürümesi:

ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
  memcpy( mat, src, sizeof( src ) );    /* NOT the same as 3*3*sizeof(float) */
}

2
"Bu değişkenin nerede kullanıldığını görmek için hızlı tarama .... her zaman bu yanlış anlama şansı vardır" - bana göre bu sizeof (tür) yapmanın en büyük tehlikesi, bu yüzden hep sizeof (değişken) yapıyordum. Çünkü bu tehlikenin sonucu her şey hala derlenebilir ve bir hata yapsanız bile, sizi yakalamadan önce bir yıldan fazla sürebilir veya rastgele çökmeler ve tampon bozulmaları olabilir. Ve bu soru ile "işaretçi yönlendirme hataları" arasındaki bağlantıyı (açıkça soru başına zaman pencerem yaklaşık 30 saniyedir) kuramadım.
DXM

@DXM İşlenenin büyüklüğü ile, eğer bir değerse o zaman sizeof var; bir işaretçi ise sizeof *var. Bu aynı zamanda insanların yanlış anlayabileceği bir şeydir ve derleyici şikayet etmeden mutlu bir şekilde kabul eder. Bu hataların, sizeof(type)formdaki hatalardan çok daha zor olduğunu ve daha yaygın olduğunu savunuyorum .
congusbongus

1
Hem sağ hem de C tipi operatörünüz temelde bozulmuştur ve asla güvenilir olmayacaktır, bir programcı olarak yaptığınız hiçbir şey onu düzeltemez.
mattnz

Gönderi etiketlendiğinden C, C kodunu yayınlamak, C ++ kodunun sevdiği hakkında daha bilgilendiricidir mat3_t::mat3_t(...).
chux - Monica

0

Amaç, fazlalığı ortadan kaldırmaktır. Değişkenle ilgili bir işlem için sizeof kullanıyorsanız, bunu açıkça sizeof'a yansıtmalısınız. Evet, ilk örnekte olduğu gibi karışabilirsin, ama tedavi tip kullanmıyor, ama * var, amacı doğru gösteriyor.

Bu tür sorunları azaltmak için, kullanım durumunuz için eğitilmiş makrolardan, şablonlardan ve benzeri araçlardan çıplak boyutta kullanmak normaldir.

Benim Bkz SİL makro münhasıran yerine çıplak memset'in kullanılır. Kıçımı birkaç defa dolaylı yazım hatası durumlarında veya bir yapı içeriği bir vektör veya dize aldığında kurtardı ...


Ki gibi Makrolar C'nin Makro programlama kötü bir isim ...... verdi nelerdir
mattnz

@ mattnz: lütfen daha iyi bir alternatif gösterin. Soyut şeyler konuşmak, gerçekten çalışan programlar oluşturmaktan daha kolay
Balog Pal

1
Bağlantılı Makro C ++ ve bu yazı 'C' olarak etiketlendi (Farklı diller), Ada benim önerim olur.
mattnz

@ matttnz: ve aynı konu, C için benzer şekillerde nasıl uygulanacağını gösterir. Bu noktayı tamamen kaçırmış görünüyorsunuz, bu gerçek içerik uygulaması değil, ham maddeye kıyasla daha güvenli kullanım. BTW yolları da okunabilir.
Balog Pal,

0

İş mantığı seçiminizi tanımlar.

  1. Kodunuz belirli bir değişkene atıfta bulunuyorsa ve bu değişken olmadan kodunuz mantıklı değildir - seçin sizeof(var)

  2. Kodlarsanız, belirli tipte bir değişkenler kümesiyle ilgileniyorsanız - seçin sizeof(type). Genellikle typedef, türüne göre farklı işlem yaptığınız birçok değişkeni tanımlayan bir şeye sahipseniz buna ihtiyacınız vardır (örneğin seri hale getirme). Bu değişkenlerden hangisinin gelecekteki kod sürümlerinde kalacağını bilemeyebilirsiniz, bu nedenle argüman olarak tür seçimi mantıksal olarak doğrudur. Böyle bir typedefşeyi değiştirmek bile sizf satırınızı etkilemeyecektir.


-1

Amacına bağlı olarak sizeof (değişken) en iyi çözüm olabilir. Bu şekilde, tür için tüm girişleri düzeltmeden, gerekirse değişken türünüzü değiştirebilirsiniz. Fakat yine de, amacınıza bağlı.

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.