[Çözüldü] static, extern Anahtar Sözcükleri Kullanımı ile İlgili Bir Soru

Başlatan blacksnow, 10 Temmuz 2015 - 00:44:11

« önceki - sonraki »

0 Üyeler ve 1 Ziyaretçi konuyu incelemekte.

blacksnow

static, extern ahahtar sözcüklerini anlamak için örnekler yapıyordum ve extern anahtar sözcüğünü kullansam da kullanmasam da bir değişiklik olmadığını gördüm.Global değişkenlerin otomatik olarak extern varsayıldığını tahmin ediyorum.Eğer öyleyse extern kelimesi gereksiz bir kelime mi oluyor?Cevaplarınız için şimdiden teşekkürler.

/* file1.c */
#include<stdio.h>

void foo(int);
extern int var;             // Burada (int var;) yazdığımda da aynı sonucu alabiliyorum

void main (void)
{
foo(var);
}


/* file2.c */
#include<stdio.h>

int var = 30;

void foo(int var)
{
printf("var = %d\n", var);
}

heartsmagic

http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

Alıntı YapNow let us the take the second and final case i.e. use of extern with C variables. I feel that it more interesting and information than the previous case where extern is present by default with C functions. So let me ask the question, how would you declare a C variable without defining it? Many of you would see it trivial but it's important question to understand extern with C variables. The answer goes as follows.

    extern int var;

Here, an integer type variable called var has been declared (remember no definition i.e. no memory allocation for var so far). And we can do this declaration as many times as needed. (remember that declaration can be done any number of times) So far so good. :)

Now how would you define a variable. Now I agree that it is the most trivial question in programming and the answer is as follows.

    int var;

Here, an integer type variable called var has been declared as well as defined. (remember that definition is the super set of declaration). Here the memory for var is also allocated.

Güzelce örneklerle de açıklanmış.
Hayattan çıkarı olmayanların, ölümden de çıkarı olmayacaktır.
Hayatlarıyla yanlış olanların ölümleriyle doğru olmalarına imkân var mıdır?


Böylece yalan, dünyanın düzenine dönüştürülüyor.

blacksnow

Aradaki farkı anlıyorum fakat bu benim ne işime yarar anlamadım.Çünkü bir değişkeni bildiriyorsam eninde sonunda ben bu değişkeni tanımlayacağım.Yani en başta extern yazmak yerine (int var;) yazarak değişkeni tanımlasam ne farkeder?Sonuçta extern yazsamda yazmasam da değişken diğer kaynak dosyasından görülebiliyor.

heartsmagic

http://stackoverflow.com/a/10422050

Benim anladığım kullanım şekli buradaki örnekteki gibi. Bir header dosyasında bildirimi yapılıyor, ihtiyaç olduğundaysa ilgili dosyada tanımlanması yapılıyor. Böylece tanımlandığı anda kaynak tahsisi oluyor.
Hayattan çıkarı olmayanların, ölümden de çıkarı olmayacaktır.
Hayatlarıyla yanlış olanların ölümleriyle doğru olmalarına imkân var mıdır?


Böylece yalan, dünyanın düzenine dönüştürülüyor.

blacksnow

Alıntı YapBenim anladığım kullanım şekli buradaki örnekteki gibi. Bir header dosyasında bildirimi yapılıyor, ihtiyaç olduğundaysa ilgili dosyada tanımlanması yapılıyor. Böylece tanımlandığı anda kaynak tahsisi oluyor.
Sizin de dediğiniz gibi ihtiyaç olduysa, ihtiyaç olmasa ben neden bildirim yapayım.Belki işime yarar belki yaramaz diye değişken yazılması mantıksız.Verdiğim örnekte de tanımlamayı file.c dosyasında yaptığımda da (int var;) derleyici bunu file2.c dosyasındaki var değişkenine bağlayabiliyor.Yani extern kullanımı sadece kaynak tahsisinin nerde yapılacağını değiştirebiliyor, başka değiştirdiği bir şey yok.Benim anlayabildiklerim bunlar.Teşekkürler.

Reverser

gayet güzel açıklanmış bence [1]
"extern" changes the linkage. With the keyword, the function / variable is assumed to be available somewhere else and the resolving is deferred to the linker.

There's a difference between "extern" on functions and on variables: on variables it doesn't instantiate the variable itself, i.e. doesn't allocate any memory. This needs to be done somewhere else. Thus it's important if you want to import the variable from somewhere else. For functions, this only tells the compiler that linkage is extern. As this is the default (you use the keyword "static" to indicate that a function is not bound using extern linkage) you don't need to use it explicitly." 

[1] http://stackoverflow.com/questions/496448/how-to-correctly-use-the-extern-keyword-in-c
[2] http://www.kaanaslan.com/resource/article/display_article.php?id=92
[3] https://msdn.microsoft.com/tr-tr/library/0603949d.aspx

özellikle 2. bağlantıyı mutlaka oku.



XFCE ROCKS !
Powered by Thunar & XFWM4



blacksnow

extern kullanıldığında bellekten yer ayrılmadığının farkındayım.Benim de size soruduğum bunun gerçekten bir önemi olup olmadığı.Çünkü sonuçta ben bu değişkeni extern ile bildirdiysem, bir yerlerde bu değişkenin tanımını yapacağım demektir, yani bellekten bir yer ayıracağım bu değişken için.Sizden beklediğim söylediklerimin mantıklı mı yoksa mantıksız mı olduğunu söylemeniz aslında.Çünkü verdiğiniz linklerin çoğunu daha önce ben de okudum ve bu sorularıma cevap bulamadığım için bu soruyu buraya yazıyorum.

Düzeltme: "extern kullanıldığında ..."


Mesaj tekrarı yüzünden mesajınız birleştirildi. Bu mesajın gönderim tarihi : 10 Temmuz 2015 - 19:28:18

extern kelimesinin birden fazla değişken içeren başlık dosyalarında (header files) mantıklı olduğunu farkettim.Eğer bir başlık dosyasında dışsal bağlanımı olan değişkenler için extern kelimesini kullanmazsam otomatik olarak yine dışsal bir bağlantısı olacak fakat değişkenlerin sadece birkaçını kullanırsam, bu durumda kullanmadıklarım içinde bellekten yer ayrılacak ve bellek israfı oluşacak.

Yukarıda yazdıklarımı herhangi bir yerden okumadım.Bu yüzden doğruluğu konusunda en azından yorumlarınızı bekliyorum.

Amenofis

Bunun bellek israfı ile alakası yok. Kim takar birkaç bytelık israfı?

Önemli olan sen bu veriyi paylaşmak istiyor musun istemiyor musun? Yani sorun algoritmik. Her C modülü kendi global verisine sahip olacaksa hepsi için static olarak bildirim yapılmalı (bu farklı isim vermekle aynı şey). Yok eğer tek nesneyi paylaşacaklarsa sadece birinde bildirim yapılır, diğerlerine extern ile bilgi verilir.

Eğer aynı isimli global veri ne static ne de extern değilse bu durumda belirsizlik ortaya çıkıyor. Eğer değişkenleri = ile hazırlamazsanız derleyici extern olduğunu varsayıyor, tabiki biri hariç. O birisinin hangisi olduğu zannedersem belirsiz, ancak emin değilim. Birden fazla global değişkeni = ile hazırlamaya çalışırsanız linker hatası verir çünkü aynı aynı kapsamda aynı isimde nesne/fonksiyon olamaz.

C++ ile denediğimde belirsizlik yok. = ile hazırlamasak dahi derleyici = 0; yapmışız gibi davranıyor ve "multiple definition" hatası veriyor. Bu durumda ya extern ya da static belirteci ile bilgilendirmek gerekiyor.

blacksnow

C++ ile dediğiniz gibi hata alıyorum ve extern ile belirtmek zorunda kalıyorum fakat c' de bir belirsizlik var.
Alıntı YapBunun bellek israfı ile alakası yok. Kim takar birkaç bytelık israfı?
Büyük çaplı bir programda ortak değişkenlerin başlık dosyalarında extern ile belirtilmemesinin (zaten okuduklarıma göre başlık dosyaları sadece bildirim için kullanılıyormuş, tanımlamalar .c dosyalarında yapılıyormuş) ciddi bellek israfı oluşturabileceğini düşünüyorum.Çünkü o değişkenler için kaynak tahsis ediliyor fakat hiç kullanılmıyor.
Alıntı YapEğer değişkenleri = ile hazırlamazsanız derleyici extern olduğunu varsayıyor, * tabi ki biri hariç. O birisinin hangisi olduğu zannedersem belirsiz, ancak emin değilim.
Kusura bakmayın biraz anlama özürlüyüm.Birisi hariç derken bir veri tipinden mi bahsediyordunuz?

Amenofis

"Ortak değişkenlerin" diyorsun bak. Değişken ortak ise zaten extern olmak ZORUNDA. static olursa eğer modüllerden birinde yapılan değişikliği diğerleri görmez, algoritmik hata oluşur. Yani extern ile bellek tasarrufunun hiçbir ilişkisi yok.

Şu şekilde örneklendireyim. a.c ve b.c isminde iki modülümüz var. İkisinde de "static bool flag;" diye global değişkenlerimiz var. b.c dosyası bir işlem yapıyor ve işlem bitince flag'ı true yapıyor olsun. a.c ise bu değişkeni kontrol ediyor olsun. Bu durumda a.c işlem bitse bile haberdar olmayacak, sonsuza kadar bekleyecek. Gördüğün gibi kaybedilen şey birkaç bytetan fazlası.

Alıntı YapKusura bakmayın biraz anlama özürlüyüm.Birisi hariç derken bir veri tipinden mi bahsediyordunuz?
Gece vakti yine kafam karışmış sen kusura bakma. Paylaşılan değişkenlerin sadece tek kopyası olmak zorunda olduğundan hangisinin extern olup olmadığın bir önemi yok. C' de denediğimde hepsini extern yapsak bile yine bir kopya oluşturuyor derleyici, kuralları gevşek olduğu için "senin yerine ben yapayım abi" diyor. C++ ise kuralları daha sert olduğu için "undefined reference" diyor.

blacksnow

Alıntı yapılan: Amenofis - 11 Temmuz 2015 - 13:35:04
"Ortak değişkenlerin" diyorsun bak. Değişken ortak ise zaten extern olmak ZORUNDA. static olursa eğer modüllerden birinde yapılan değişikliği diğerleri görmez, algoritmik hata oluşur. Yani extern ile bellek tasarrufunun hiçbir ilişkisi yok.
Değişken ortak ise extern olmak zorunda, bu c++ ile geçerli fakat c'de olmasa da olabiliyor.Bu neden böyle onu da anlamış değilim.Birde şunu farkettim c'de eğer iki aynı değişkene bir değer atılırsa tanımlama esnasında farklı dosyalarda c++' daki gibi hata veriyor o da.Fakat birisi ilklenir birisi ilklenmezse ilklenen değişkenin değeri yazılıyor ve ortak oluyor.Belki extern bunun için tasarlanmamıştır ama yine de bellek kaybını önleyebileceğini düşünüyorum.Ayrıca verdiğiniz örnekteki bellek kaybını tam anlamadım kusura bakmayın fakat benim bahsettiğim bellek kaybı daha farklı.

Düzenleme 1:
Bellek tasarrufu konusunda sanırım hatalıyım çünkü bir başlık dosyasında eğer bildirilmişse değişken, kaynak dosyalar beraber derleneceği için extern yazsak da yazmasak da hepsi için yer ayrılacak bellekten.Hangi kaynağı okuduysam bir değişkenin dışa bağlantısı varsa extern ile belirtilmesi gerektiği söyleniyor.Ama belirtmesek de oluyor.Neden böyle bir açık var?C++'da ne güzel hata veriyor.Ben mi kendimi çok zorluyorum, bu kadar ayrıntıya girmem iyi mi değil mi düşünmeye başladım.

Düzenleme 2:
Aradığım cevabı buldum, şu şekilde;
http://stackoverflow.com/questions/16542258/c-implicit-extern-for-global-variable-when-does-it-happen-how-does-it-work
Alıntı Yap/* file.h */
int* i;

is a tentative definition of the i variable. This means that if there is no other (external) definition for that variable in the translation unit, it will be defined just once (initialized to 0). If there is exactly one matching (external) definition of i elsewhere in the translation unit, that definition will be used, and the tentative definition above will behave as a declaration.
Buradaki açıklama benim için yeterli oldu fakat nerede işime yarar bu durum bilmiyorum.Konuyu burada noktalıyorum.Yardım eden etmeyen herkese teşekkürler.

Amenofis

Bir değişkeni paylaşmanın ne kadar kritik bişey olduğunu anlatmaya çalıştım ama sanırım anlaşılmadı. Dışa bağlantı falan bunlar gereksiz laflar. Paylaşmak ya da paylaşmamak, işte bütün mesele bu. Bu konuyu anlamak istiyorsan veri paylaşımı yapan bir uygulama yaz. Hatta bunu thread ler ile yap. Global değişkenlerden girer atomic nesnelerden çıkarsın. Bayağı öğretici olur.

Bu arada C' de sen extern yazmasan dahi duruma göre derleyici yazıyor onu. "Yazmadım ama yine de oluyor" diye bişey yok.

blacksnow

@Amenofis, konu anlaşıldı merak etmeyin.Thread ler, atomic nesneleri dahaca öğrenmedim.Kesinlikle örnek uygulamalar yapılması gerektiğine katılıyorum.Bunlar işin teorik kısmı, işin içine girdiğimizde daha nelerle karşılaşacağız bakalım.Tekrardan teşekkürler.