Ne yazdırılacak? 6 6 veya 6 7? Ve neden?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Ne yazdırılacak? 6 6 veya 6 7? Ve neden?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Yanıtlar:
Burada iki konu var, ömür ve kapsam.
Değişkenin kapsamı, değişken adının görülebildiği yerdir. Burada x yalnızca foo () işlevi içinde görülebilir.
Bir değişkenin yaşam süresi, var olduğu dönemdir. Eğer x, static anahtar sözcüğü olmadan tanımlandıysa, yaşam süresi foo () girişinden foo () dönüşüne kadar olacaktır; bu nedenle her aramada 5 olarak yeniden başlatılır.
Statik anahtar sözcüğü, bir değişkenin ömrünü programın yaşam süresine uzatır; Örneğin, başlatma yalnızca bir kez ve bir kez gerçekleşir ve sonra değişken - ne olursa olsun - gelecekteki tüm foo () çağrılarında değerini korur.
Çıkış : 6 7
Nedeni : statik değişken yalnızca bir kez başlatılır (otomatik değişkenin aksine) ve statik değişkenin daha fazla tanımı çalışma sırasında atlanır. Ve manuel olarak başlatılmazsa, otomatik olarak 0 değeri ile başlatılır. Yani,
void foo() {
static int x = 5; // assigns value of 5 only once
x++;
printf("%d", x);
}
int main() {
foo(); // x = 6
foo(); // x = 7
return 0;
}
6 7
derleyici, işlev her girildiğinde statik değişken başlatmanın gerçekleşmeyeceğini düzenler
Bu, aşağıdaki programa sahip olmakla aynıdır:
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Statik anahtar kelimenin o programda yaptığı tek şey, derleyiciye (esasen) 'hey, burada başka kimsenin erişmesini istemediğim bir değişkenim var, onun var olduğunu kimseye söylemeyin' demesidir.
Bir yöntemin içinde, static anahtar sözcüğü derleyiciye yukarıdakiyle aynı şeyi söyler, ancak aynı zamanda 'kimseye bunun bu işlevin dışında olduğunu söylemeyin, yalnızca bu işlev içinde erişilebilir olmalıdır'.
Umarım bu yardımcı olur
x
esas olarak dürtebilir ve futz yapabilirsiniz ; küreseldir. Orijinal örnekte x
local to foo idi, sadece bu bloğun içindeyken görülebilir, ki bu genellikle tercih edilir: eğer foo x
öngörülebilir ve görünür yollarla sürdürmek için varsa , o zaman başkalarının onu dürtmesine izin vermek genellikle tehlikelidir. Kapsamda tutmanın bir başka yararı foo()
da foo()
taşınabilirliğini koruyor.
c
, bu nedenle bu bağlamda, örneğiniz küresel kapsamda yasadışı olacaktır. (C küreseller için sabit başlatıcılar gerektirir, C ++ gerektirmez).
Bir işlevin içindeki statik bir değişkenin, programınız çalıştığı sürece bir ömrü vardır. İşleviniz her çağrıldığında ve işleviniz geri döndüğünde serbest bırakıldığında tahsis edilmeyecektir.
Beyanı x
içeride, foo
ancak x=5
başlatma dışında gerçekleşiyor foo
!
Burada anlamamız gereken şey şudur:
static int x = 5;
ile aynı değil
static int x;
x = 5;
Diğer cevaplar burada önemli kelimeleri, kapsam ve yaşam süresini kullanmış ve kapsamının x
işlevdeki bildirimi noktasından işlevin foo
sonuna kadar olduğuna işaret etmiştir foo
. Örneğin, bildirimi işlevin sonuna taşıyarak kontrol ettim ve bu x
, x++;
ifadede bildirilmemiş hale getiriyor .
Dolayısıyla, static int x
ifadenin (kapsam) kısmı, onu okuduğunuz yerde , işlevin İÇİNDE bir yerde ve yalnızca oradan itibaren geçerlidir, işlevin içinde değil.
Bununla birlikte x = 5
ifadesinin (ömrü) bir parçası olan değişken başlatma ve oluyor dışında program yükleme parçası olarak işlev. Değişken x
, 5
programın ne zaman yüklendiğinin bir değeriyle doğar .
Bunu yorumlardan birinde okudum: " Ayrıca, bu gerçekten kafa karıştırıcı kısma değinmiyor, bu da başlatıcının sonraki aramalarda atlanması gerçeğidir. " Tüm aramalarda atlanır. Değişkenin ilklendirilmesi uygun fonksiyon kodunun dışındadır.
5'in değeri teorik olarak foo'nun çağrılıp çağrılmadığına bakılmaksızın ayarlanır, ancak bir derleyici işlevi herhangi bir yerde çağırmazsanız işlevi dışarıda optimize edebilir. Foo çağrılmadan önce 5'in değeri değişkenin içinde olmalıdır.
İçinde foo
, ifadenin static int x = 5;
herhangi bir kod üretmesi olası değildir.
Bir programıma x
bir işlev koyduğumda adres kullanımlarını buldum foo
ve daha sonra (doğru) programı tekrar çalıştırırsam aynı konumun kullanılacağını tahmin ettim. Aşağıdaki kısmi ekran görüntüsü x
, değere 5
ilk çağrıdan bile önce sahip olduğunu gösterir foo
.
Çıktı olacak 6 7
. Statik bir değişken (bir işlevin içinde olsun ya da olmasın), o çeviri birimindeki herhangi bir işlev yürütülmeden önce tam olarak bir kez başlatılır. Bundan sonra, değiştirilene kadar değerini korur.
Vadiklk,
Neden ...? Nedeni, statik değişkenin yalnızca bir kez başlatılması ve tüm program boyunca değerini korumasıdır. işlev çağrıları arasında statik değişken kullanabileceğiniz anlamına gelir. ayrıca "bir işlevin kaç kez çağrıldığını" saymak için de kullanılabilir
main()
{
static int var = 5;
printf("%d ",var--);
if(var)
main();
}
ve cevap beklediğiniz gibi 5 4 3 2 1 değil 5 5 5 5 5 5 .... (sonsuz döngü). yine, neden statik değişkenin bir kez başlatılmasıdır, bir dahaki sefere main () çağrıldığında, programda zaten başlatıldığından 5'e başlatılmayacaktır.Yani değeri değiştirebiliriz ama yeniden başlatamayız. Statik değişken böyle çalışır.
veya depolamaya göre düşünebilirsiniz: statik değişkenler bir programın Veri Bölümünde depolanır ve Veri Bölümünde depolanan değişkenler bir kez başlatılır. ve başlatmadan önce BSS bölümünde tutulurlar.
Buna karşılık, Otomatik (yerel) değişkenler Yığın üzerinde saklanır ve yığındaki tüm değişkenler, işlev yeni FAR (işlev etkinleştirme kaydı) olarak çağrıldığında bunun için her zaman yeniden başlatılır.
tamam, daha fazla anlayış için, yukarıdaki örneği "statik" olmadan yapın ve çıktının ne olacağını size bildirin. Bu, bu ikisi arasındaki farkı anlamanızı sağlar.
Teşekkürler Javed
Let sadece okumuş Statik Değişkenler Wikipedia article ...
Statik yerel değişkenler: Bir işlev içinde statik olarak bildirilen değişkenler, otomatik yerel değişkenlerle aynı kapsama sahipken statik olarak ayrılır. Dolayısıyla, bir çağrı sırasında işlevin statik yerel değişkenlerine koyduğu değerler, işlev yeniden çağrıldığında hala mevcut olacaktır.
Kolayca test edildiği gibi 6 7 yazdırılacak ve bunun nedeni foo
şudur: İlk çağrıldığında, x statik değişkeni 5 olarak başlatılır. Daha sonra 6'ya yükseltilir ve yazdırılır.
Şimdi bir sonraki çağrı için foo
. Program statik değişken başlatmayı atlar ve bunun yerine en son x'e atanan 6 değerini kullanır. Uygulama normal şekilde ilerler ve size 7 değerini verir.
6 ve 7 Statik değişken yalnızca bir kez yapıldığından, So 5 ++ 1. çağrıda 6 olur 6 ++ 2. çağrıda 7 olur Not - 2. çağrı gerçekleştiğinde x değeri 5 yerine 6 alır çünkü x statik değişkendir.
En azından C ++ 11'de, yerel bir statik değişkeni başlatmak için kullanılan ifade bir 'constexpr' değilse (derleyici tarafından değerlendirilemez), o zaman ilk işlev çağrısı sırasında başlatma yapılmalıdır. En basit örnek, yerel statik değişkeni başlatmak için doğrudan bir parametre kullanmaktır. Bu nedenle derleyicinin, çağrının ilk olup olmadığını tahmin etmek için kod vermesi gerekir, bu da yerel bir mantıksal değişken gerektirir. Böyle bir örneği derledim ve montaj kodunu görerek bunun doğru olduğunu kontrol ettim. Örnek şu şekilde olabilir:
void f( int p )
{
static const int first_p = p ;
cout << "first p == " << p << endl ;
}
void main()
{
f(1); f(2); f(3);
}
Tabii ki, ifade 'constexpr' olduğunda, bu gerekli değildir ve değişken, çıktı derleme kodunda derleyici tarafından saklanan bir değer kullanılarak program yükünde başlatılabilir.