C'de keyfi blokların deyimsel kullanımı nedir?


15

Blok, yürütülecek deyimlerin listesidir. C'de blokların nereden geldiğine ilişkin örnekler bir while ifadesinden sonra ve if ifadelerinde

while( boolean expression)
    statement OR block

if (boolean expression)
    statement OR block

C ayrıca bir bloğun bir bloğa yuvalanmasını sağlar. Değişken isimlerini yeniden kullanmak için bunu kullanabilirim, 'x' gerçekten hoşuma gitti

int x = 0;
while (x < 10)
{
    {
        int x = 5;
        printf("%d",x)
    }
    x = x+1;
}

5 sayısını on kez yazdıracaktır. Değişken adlarının düşük tutulmasının arzu edildiği durumları görebiliyordum. Belki makro genişlemede. Ancak, bu özelliğe ihtiyaç duymak için zor bir neden göremiyorum. Herkes, kullanıldığı yerde bazı deyimler sağlayarak bu özelliğin kullanımlarını anlamama yardımcı olabilir.


1
Dürüst olmak gerekirse, sadece C sözdizimini anlamaya çalışıyorum ve merak ediyorum.
Jonathan Gallagher

C'nin ruhu programcıya güvenmektir. Programcı harika bir şey yapma ya da korkunç bir şey yapma gücüne sahiptir. Şahsen, aşırı değişken adları sevmiyorum ama başka bir programcı olabilir. Günün sonunda, asgari hatalarla yapmamız gereken şeyi başarırsak ... neden tartışmalıyız?
Fiddling Bits

1
Bu C'den aldığım duygu. Hepimiz farklı kodlama stillerini destekleyen sözdizimindeyim (dilin anlambilimi iyi olduğu sürece). Sadece ... Bunu gördüm ve hemen yanıtım, bir bloktaki tüm değişkenleri yeni isimlerle yeniden adlandıran ve bloğu tamamen düzeltebildiğim kaynaktan kaynağa bir dönüşüm uygulayabilirdim. Ne zaman bir şeyden kurtulabileceğimi düşünüyorum, kaçırdığım bir şey olduğunu varsayıyorum.
Jonathan Gallagher

Komik zamanlama, C olmayan bir programcı olarak bu sözdiziminde bugün C kodunda tökezledim ve bunun ne için olduğunu merak ettim. Sorduğun için minnettarım.
Brandon

Yanıtlar:


8

Fikir, değişken adlarının sayısını düşük tutmak veya adların yeniden kullanılmasını teşvik etmek değil, değişkenlerin kapsamını sınırlamaktır. Eğer varsa:

int x = 0;
//...
{
    int y = 3;
    //...
}
//...

o zaman kapsamı yblokla sınırlıdır, yani bloktan önce veya sonra onu unutabilirsiniz. Bunun en çok döngüler ve koşullarla bağlantılı olarak kullanıldığını görürsünüz. Ayrıca, kapsam dışında kalan bir değişkenin yok olmasına neden olan C ++ gibi C benzeri dillerde daha sık görürsünüz.


Bence blok doğal olarak şartlar, döngüler ve fonksiyon bedenleri ile meydana gelir. Merak ettiğim şey, C'ye herhangi bir yere bir blok yerleştirebileceğim. C ++ ile ilgili ikinci yorumunuz ilginç - bir kapsamı terk etmek yıkıma neden oluyor. Bu sadece çöp toplama anlamına mı geliyor, yoksa şu başka bir kullanım mı? Farklı "bölümleri" olan bir işlev gövdesi alabilir ve değişken alanın yok edilmesini tetikleyerek bellek ayak izini kontrol etmek için blokları kullanabilir miyim?
Jonathan Gallagher

1
Bildiğim kadarıyla, C fonksiyondaki tüm değişkenler için tüm belleği önceden tahsis edecektir. Bir işlevden kapsamdan kısmen çıkmalarının C'de hiçbir performans avantajı olmayacaktır. Benzer şekilde değişkenlerin kapsamı "yalnızca bazen" girmesi, işleve yapılan herhangi bir çağrı sırasında bellek ayak izini değiştirmez
Gankro

@Gankro Birden fazla özel iç içe kapsam varsa, bu durumun bir etkisi olabilir. Bir derleyici, bu kapsamların her birindeki değişkenler için önceden tanımlanmış benzersiz bir bellek yığınını yeniden kullanabilir. Elbette akla gelmemesinin nedeni, tek bir keyfi kapsam zaten bir işaretse, muhtemelen bir işleve çıkarmanız gerektiğidir, iki veya daha fazla keyfi kapsamın kesinlikle yeniden düzenlemeniz gereken iyi bir göstergedir. Yine de, zaman zaman anahtar kutusu blokları gibi şeylerde akılcı bir çözüm olarak ortaya çıkıyor.
tne

16

Çünkü C'nin eski günlerinde yeni değişkenler sadece yeni bir blokta bildirilebilirdi.

Bu şekilde programcılar, bir işlevin ortasına sızmadan ve yığın kullanımını en aza indirmeden yeni değişkenler ekleyebilir.

Günümüz optimizatörleri ile işe yaramaz ve bloğu kendi işlevinde çıkarmayı düşünmeniz gereken bir işarettir.

Bir anahtar ifadesinde, çift bildirimi önlemek için vakaları kendi bloklarına dahil etmek yararlıdır.

C ++ 'da, örneğin RAII kilit korumaları ve yürütme kapsam dışına çıktığında ve kritik bölümün dışında başka şeyler yaparken yıkıcıların serbest bırakma kilidini çalıştırmasını sağlamak için çok yararlıdır.


2
RAII kilit korumaları için +1. Bununla birlikte, aynı kavram, bir rutinin parçaları içinde büyük-ish yığın tamponu dağıtımı için de yararlı olamaz mı? Ben hiç yapmadım, ama kesinlikle bazı gömülü kodda meydana gelebilecek bir şey gibi geliyor ...
J Trana

2

Buna "keyfi" bloklar olarak bakmazdım. Bu, geliştirici kullanımı için çok önemli bir özellik değildir, ancak C'nin blokları kullanma şekli, aynı blok yapısının aynı semantiğe sahip birçok yerde kullanılmasına izin verir. Bir blok (C cinsinden) yeni bir kapsamdır ve onu bırakan değişkenler elimine edilir. Bu, bloğun nasıl kullanıldığından bağımsız olarak aynıdır.

Diğer dillerde, durum böyle değil. Bu, gösterdiğiniz gibi daha az kötüye kullanıma izin verme avantajına sahiptir, ancak blokların dezavantajı, içerdikleri içeriğe bağlı olarak farklı davranır.

C veya C ++ 'da kullanılan bağımsız blokları nadiren gördüm - genellikle büyük bir yapı veya bir bağlantıyı veya yıkımı zorlamak istediğiniz bir şeyi temsil eden bir nesne olduğunda. Genellikle bu, işlevinizin çok fazla şey yaptığına ve / veya çok uzun olduğuna dair bir ipucudur.


1
Ne yazık ki düzenli olarak bağımsız bloklar görüyorum - neredeyse tüm durumlarda işlev çok şey yapıyor ve / veya çok uzun.
mattnz

Ayrıca düzenli olarak C ++ 'da bağımsız bloklar görüyor ve yazıyorum, ancak sadece kilitlerin ve diğer paylaşılan kaynakların etrafındaki sarmalayıcıların yok edilmesini sağlamak için.
J Trana

2

Fark etmelisiniz, şimdi belirgin görünen programlama ilkeleri her zaman böyle değildi. C'nin en iyi uygulamaları büyük ölçüde örneklerinizin kaç yaşında olduğuna bağlıdır. C ilk kez tanıtıldığında, kodunuzu küçük işlevlere bölmek çok verimsiz olarak kabul edildi. Dennis Ritchie temel olarak yalan söyledi ve C'de fonksiyon çağrısı gerçekten etkili olduğunu söyledi (o zamanlar değildi), bu da insanları daha fazla kullanmaya başladı, ancak C programcıları bir şekilde gerçekten erken optimizasyon kültürünü geçemediler.

İse mümkün olduğu kadar küçük değişkenlerinizin kapsamını sınırlamak için bugün bile iyi bir programlama uygulama. Günümüzde, bunu genellikle yeni bir işlev oluşturarak yapıyoruz, ancak işlevler pahalı sayılırsa, yeni bir blok eklemek, bir işlev çağrısı yükü olmadan kapsamınızı sınırlamanın mantıklı bir yoludur.

Bununla birlikte, 20 yıl önce C'de programlamaya başladım, geri döndüğünüzde tüm değişkenlerinizi bir kapsamın üstünde beyan etmek zorunda kaldınız ve değişken gölgelemeyi iyi bir stil olarak hatırlamıyorum. Bir switch deyiminde olduğu gibi birbiri ardına iki blok halinde yeniden açıklama, evet, ancak gölgeleme değil. Belki değişken zaten kullanılıyor ve spesifik adı gibi aradığınız API için son derece deyimsel oldu eğer destve srcde strcpyörneğin.


1

Rasgele bloklar, yalnızca özel bir hesaplama durumunda kullanılan ara değişkenleri tanıtmak için yararlıdır.

Bu, sayısal hesaplamaların tipik olarak olduğu bilimsel hesaplamada yaygın bir modeldir:

  1. çok sayıda parametreye veya aracı miktarlara güvenin;
  2. birçok özel durumla uğraşmak zorunda.

İkinci nokta nedeniyle, keyfi bir blok kullanılarak veya yardımcı bir fonksiyon girerek elde edilen sınırlı kapsamdaki geçici değişkenlerin sokulması faydalıdır.

Yardımcı bir işlev getirmek, beyinsiz veya körü körüne takip etmek için en iyi uygulama gibi görünse de , bu özel durumda bunun pek az faydası vardır .

Çok sayıda parametre ve ara miktar olduğundan, bunları yardımcı fonksiyona geçirecek bir yapı tanıtmak istiyoruz.

Ancak, uygulamalarımızla sonuçlanmak istediğimiz için, sadece bir yardımcı işlevi değil, birkaçını da tanıtacağız. Yani, parametreleri ileri geri hareket ettirmek için çok fazla kod yükü tanıtan her bir işlev için parametreleri taşıyan geçici yapıları tanıttığımız ya da bir tanesini tanıttığımız, ya da tüm değişkenlerimizi içeren, ancak benzeyen tüm çalışma sayfası yapısını yönetecektir. herhangi bir zamanda parametrelerin sadece yarısının ilginç bir anlamı olduğu tutarlılık içermeyen bitlerin bir paketi.

Bu nedenle, bu yardımcı yapılar tipik olarak hantaldır ve bunları kullanmak, kod bloat arasında seçim yapmak veya kapsamı çok geniş olan ve programın anlamını zayıflatmak yerine anlamını zayıflatan bir soyutlama getirmek anlamına gelir .

Yardımcı fonksiyonların tanıtılması, daha ince bir test zerresi sunarak programın birim testini kolaylaştırabilir, ancak düşük seviye prosedürleri ve prosedürlerin sayısal izlerinin karşılaştırılması (numdiff ile) regresyon testlerini eşit derecede iyi bir iş haline getirmediği için birim testini birleştirir. .


0

Genel olarak, değişken adlarının bu şekilde yeniden kullanılması, kodunuzun gelecekteki okuyucuları için çok fazla karışıklığa neden olur. İç değişkene başka bir ad vermek daha iyidir. Aslında, C # dili değişkenlerin bu şekilde kullanılmasına özellikle izin vermemektedir.

İç içe blokların makro genişletmelerinde kullanılmasının değişken adlandırma çakışmalarını önlemede nasıl yararlı olacağını görebiliyordum.


0

Normalde o düzeyde kapsamı olmayan şeyleri kapsamak içindir. Bu son derece nadirdir ve genel olarak yeniden düzenleme daha iyi bir seçimdir, ancak geçiş ifadelerinde geçmişte bir veya iki kez karşılaştım:

switch(foo) {
   case 1:
      {
         // bar
      }
   case 2:
   case 3:
      // baz
      break;
   case 4:
   case 5:
      // bang
      break;
}

Bakımı düşündüğünüzde, bunların yeniden düzenlenmesi, her biri yalnızca birkaç satır uzunluğunda olduğu sürece, tüm uygulamaların üst üste gelmesi ile dengelenmelidir. İşlev adlarının bir listesinden ziyade hepsini bir araya getirmek daha kolay olabilir.

Benim durumumda, doğru hatırlıyorsam, vakaların çoğu aynı kodun küçük varyasyonlarıydı - bunlardan biri, sadece ekstra ön işleme ile diğeriyle özdeşti. Bir anahtar, kodun alması için en basit form haline geldi ve ekstra kapsam, kendisinin ve daha fazla vakanın endişelenmesi gerekmeyen ekstra yerel değişkenlerin kullanılmasına izin verdi (örneğin, anahtardan önce tanımlanmış biriyle yanlışlıkla çakışan değişken adları gibi, ancak sonra kullanılır).

Anahtar deyiminin, basitçe karşılaştığım ifadenin kullanımı olduğunu unutmayın. Başka yerlerde de uygulanabileceğinden eminim, ancak bunların bu şekilde etkili bir şekilde kullanıldığını hatırlamıyorum.

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.