Fonksiyonlar arasında sıçramayı nasıl yapabilirim?

picmanya

Üye
Katılım
14 Haziran 2024
Mesajlar
15
Merhabalar,
Bu foruma üye olurken, çalışma yapısına acemi olduğumdan, resimleri taşıyarak karşılaştırma kısmını aşarken, birkaç deneme yapmak zorunda kaldım.
Bu yapıyı bilmeyenler için, geçilmesi gereken zorlu bir aşama olabilir. Belkide üye kaybınada neden olmuş bir aşama olabilir. Uğraşarak çözülebiliyor.
Yada bilinçli koyulmuşda olabilir.

Aynı fonksiyon içinde bir yere sıçramada goto - labelden haberdarım. #include <setjmp.h> LongJump SetJump yapılarını istediğim gibi kullanamadım.
Amacım fonksiyonlar arasında istediğim noktaya sıçrama yapabilmek. Yapmak istediğimi altda anlatmaya çalıştım.
Bunu nasıl yapabilirim? Lütfen beni yönlendirebilirmisiniz.
NOT:
formun metin editörü kod satıları başlarındaki girintileri atlayıp, kodları sola dayalı gösteriyor gibi duruyor. Bu kod yazımlı gösterimlerde anlaşılmayı-okumayı güçleştirebilir. Yetkili/ilgili dikkate almayı düşünürse bilgisine iletilir.

void CN_Interrupt() // işlemci giriş pin kesmesi interruptu.
{
...kodlar...
if(şartlar1) Atla_1;
...kodlar...
}

void TIMER1_Interrupt() // işlemci timer kesmesi interruptu.
{
...kodlar...
if(şartlar2) Atla_2;
...kodlar...
}

Double BolmeYap (float sayi1, float sayi2) // kullanıcı tanımlı yazılan fonksiyon.
{
...kodlar...
if(şartlar3) Atla_3;
...kodlar...
}

int main(void)
{
...kodlar...

while(1)
{
...kodlar...
...kodlar...
Atla_1:
...kodlar...
...kodlar...
Atla_2:
...kodlar...
...kodlar...
Atla_3:
...kodlar...
...kodlar...
}
}
 
Son düzenleme:
Programını editörden tekrar kopyalayıp "kod" olarak ekleyebilirsin

1718390210191.png


Senin yapmaya çalıştığın iş için bir fonksiyondan diğerine atlamaya gerek yok. setjmp ve longjmp modern programlamada gerekli olan şeyler değil.
 
normalde bir fonksiyonu ortasından çağırmaya ihtiyacın olmamalı. fonksiyonlar içinde de başka bir fonksiyona giderken recursive-içiçe çağırmalardan kaçınmalısın.

fonsiyonun yapacağı görevleri olabildiğince minimize et ya da fonksiyonun içinde switch-case veya if-else yapısı ile istedeğin alanları çalıştır.

bu label/goto yapısı aslında C dilinde tercih edilmeyen hatta yasaklanmış bir kullanım. çünkü ortalığı karıştırmak çok kolay. eğer assembly öğrenip sonradan C diline geçtiysen bu şekilde bir kullanımı denemen normal. ama kodları mantıklı yazdığında buna aslında hiç ihtiyacın olmadığını görebilirsin.
 
aygıt sürücü veya api kütüphaneleri yazarken goto nun kullanılması duruma göre çok büyük kolaylık ve kodda basitlik sağlayabiliyor, o yüzden onu kesinlikle kullanılmaması gereken birşey diye değerlendirmiyorum ben. Şöyle bir örnek vereyim. bir API fonksiyonu önce iki tane bellek ayırıyor, sonra iki tane aygıt open yapıyor, sonra bir mutex'i lock ediyor, sonra aygıtı yapılacak işe göre yapılandırıyor. İşinin bir parçası olarak bundan sonra daha da farklı işlemler yapıyor olabilir. Bu aşamaların her birisinde hata oluşabilir. Hata oluştuğunda da ilgili API fonksiyon bütün yaptığı işlemleri doğru sırada ve gerekli ise geri alması lazım. Bunu goto'lu bir yapı ile yapmak kolay, prosedürel olarak yapmak ise zor oluyor. Kodu olması gerektiğinden daha karmaşık hale getiriyor.

Ama C++ 'da "wrapper class" ler ve exception handling kullanarak bu sorun daha etkili bir şekilde çözülebiliyor. Tabi bunun da bedeli çok daha büyük bir kod boyutu. Eğer yer sorunu yoksa kesinlikle tercih edilmesi gereken yöntem bu.
 
İşlemci derleyicisi XC16 bu durumda sanıyorum C++ dilindende istifade edemem. işlemci ucuzluğu nedeniyle kısıtlı imkanlara sahip (hafıza ve hız gibi...) ve bunu kullanmak zorundayım. kararımı değiştiremediniz.! İstediğimi yapabilmem için hangi anahtar kelimelerle araştırma yapmam gerekir?
Veya #include <setjmp.h> kütüphanesi kullanılarak, LongJump ve SetJump aracılığıyla bu işi başarmam mümkünmüdür? Bunlara biraz baktım deneme yaptım, başaramadım. Bunlarla olur yapılır derseniz, ayrıntılı denemeler yapıp iyice araştırabilirim. İyi bildiğiniz gibi; goto label yapısı aynı fonksiyon içinde kullanılabiliyor. Bana goto label yapısının ayrı fonksiyonlar içinde kullanılan yapısı lazım. Yalnız ben bu yapıyı; fonksiyonları çağırmak için kullanmayacağım. Bu yapı herhangibir fonksiyon/fonksiyonların içinde kurulup, çalıştırıldığında; direkt main içindeki sonsuz döngü ile çalışan While() içerisinde bir yerlere gidilecek. fonksiyondan fonksiyona atlayıp çağırmak yok yani.
 
Son düzenleme:
aygıt sürücü veya api kütüphaneleri yazarken goto nun kullanılması duruma göre çok büyük kolaylık ve kodda basitlik sağlayabiliyor, o yüzden onu kesinlikle kullanılmaması gereken birşey diye değerlendirmiyorum ben. Şöyle bir örnek vereyim. bir API fonksiyonu önce iki tane bellek ayırıyor, sonra iki tane aygıt open yapıyor, sonra bir mutex'i lock ediyor, sonra aygıtı yapılacak işe göre yapılandırıyor. İşinin bir parçası olarak bundan sonra daha da farklı işlemler yapıyor olabilir. Bu aşamaların her birisinde hata oluşabilir. Hata oluştuğunda da ilgili API fonksiyon bütün yaptığı işlemleri doğru sırada ve gerekli ise geri alması lazım. Bunu goto'lu bir yapı ile yapmak kolay, prosedürel olarak yapmak ise zor oluyor. Kodu olması gerektiğinden daha karmaşık hale getiriyor.

Ama C++ 'da "wrapper class" ler ve exception handling kullanarak bu sorun daha etkili bir şekilde çözülebiliyor. Tabi bunun da bedeli çok daha büyük bir kod boyutu. Eğer yer sorunu yoksa kesinlikle tercih edilmesi gereken yöntem bu.
yazılımcı ne yaptığını iyi biliyorsa dile ve sisteme hakimse tabi goto veya inline assembly kullanabilir. çünkü tüm olasılıkları ve çıkacak sorunları değerlendibilecek tecrübeye sahip. ama bir acemi için goto ilk anda çok pratik ve iş gören bir komut olarak görünse de gerçek hayatta çıkarabileceği sorunlar ve sorunun nereden kaynaklandığını çözemeyeceği için başına bela olma olasılığı yüksek.
 
yazılımcı ne yaptığını iyi biliyorsa dile ve sisteme hakimse tabi goto veya inline assembly kullanabilir. çünkü tüm olasılıkları ve çıkacak sorunları değerlendibilecek tecrübeye sahip. ama bir acemi için goto ilk anda çok pratik ve iş gören bir komut olarak görünse de gerçek hayatta çıkarabileceği sorunlar ve sorunun nereden kaynaklandığını çözemeyeceği için başına bela olma olasılığı yüksek.
goto - label ikilisinden korkulacak bir problem olduğunu sanmıyorum. bir şehir efsanesidir dolaşıyor butürden bilgiler webde. goto - label ile aynı fonksiyon içinde bir yere sıçranıyor ve goto ile label arasındaki kodların işletilmeden atlanılıp label den itibaren kodların koşturulduğunu bildikten sonra, atlanılan kod/kodlarında ne işe yarayıp yaramadığını bilen, atlanılınca ve atlatılmasa ne olacağına hakim olan birisi neden ve nerde hata yapsınki? sonucda aynı fonksiyon içinde dolaşılıyor. Burda kolay hata yapmaya müsait olan birisi, buraya gelene kadar da bir çok yerde de hatayı zaten yapabilir. Şimdi suçlu goto label mi olsun. Çok büyük kolayalık sağlıyor ve avantaj sağlıyor. While() içinde çok kullandım. Kullanmadan işin içinden çıkılamayacak kısımlarda olabiliyor. Kullanmadan onlarca satır kod yazmak ilave fonksiyonlar tanımlamak gerekebiliyor bazen. Bu ilavelerde dert bunlardanda sorun çıkabilir. Dertsiz sorunsuz iş yokki. Avantajlısını kullanmak lazım derim.

Fonksiyonlar arasında sıçramayı nasıl yapabilirim. Yada #include <setjmp.h> LongJump SetJump kısımları bu işi yapabiliyormu? BİLEN VARMI?
 
Programın herhangi bir yerine istediğiniz zaman gitmek için yöntemi açıklıyorum. Fonksiyon içi veya dışı fark etmez.

Öncelikle gidilecek konumun adresi bilinmeli.
Derleme esnasında sabit adresler tanımlanarak bu iş kolay oluyordu. Fonksiyonların sabit adresi varsa veya label konumu sayesinde dallanma yapılır?

Adresler bilinmiyorsa program açılışında bir defa çalışacak fonksiyonla gidilecek konumlar bir diziye depolanır.

Gerekli yerde dallanmayı sağlayan makro kullanılır.
 
Son düzenleme:
face80, Hocam
Uzman bir programcı değilim. Bahsettiğiniz yapıyada yabancıyım. Bu tarz bir çalışmayı ilk kez duydum. Bu yüzden yazdıklarınızı pek anlayamadım.
Rica etsem, altdaki kısa kod satırları üzerinden anlatmanız mümkünmüdür? Bu arada XC16 derleyicisini kullanıp, yalnızca C dili ile program yazmayı kısmen becerebiliyorum. Asm / Assembly kullanmışlığım ve bilgim hiç yok.
_________________________________________________________________________________________________________________________________________________________________________
void CN_Interrupt() // işlemci CN giriş pinleri kesmesi interruptu.
{
...kodlar...
if(şart) Git1;
...kodlar...
}

void Kullanıcı(void) // kullanıcı tanımlı yazılan fonksiyon.
{
...kodlar...
if(şart) Git2;
...kodlar...
}

int main(void)
{
...kodlar...

while(1)
{
...kodlar...
Git1:
...kodlar...
...kodlar...
Git2:
...kodlar...
...kodlar...
}
}
_________________________________________________________________________________________________________________________________________________________________________
Bildiğiniz gibi, üstdeki programın tercümesi :
program main() fonksiyonundan başlayıp, daha sonrasında while() döngüsü içerisinde sürekli çalışır. while() döngüsü dışına yalnızca, üstdeki kesme fonksiyonu ve kullanıcı tanımlı fonksiyona gitmek gerektiğinde çıkılıp, tekrar while() içerisine geri kalınan yere geri dönülür.
Ben istiyorumki; while() döngüsünde kalınan yere geri dönüleceği anda, geri dönülecek konumu ben kendim belirleyebileyim. Bunu göstermek için temsilen üstdeki fonksiyonların içerisinde Git1; Git2; komutlarını kullandım. Bu kısımlar işletildiğinde gidilecek konumlarıda while() döngüsü içerisinde altda Git1: Git:2 ile belirttim. Kısaca Git1; işletilirse.... Git1: e gidilsin istiyorum. Bu durumda Git1 sonrasındaki fonksiyon içindeki kalan kod-komut kısımları ile, while() döngüsü içerisindeki Git1: öncesindeki kodlar-komutlar işletilmemesi gerekir. Satır adreslerini almakmı gerekiyor? Adres alınma kısmınıda bilemedim.
Yetkiliye Yediden Not:
Not padden kodlar kopyalanıp yapıştırıldığında kod satırları girintisi kayboluyor. Buradaki editördede bunu düzenlemenin faydası görülemiyor. Bu kısma bakacaksa forum düzenleyicisi bakabilir ancak. Sorun benden kaynaklı değil !.... Bakılması gerekmiyorsada problem değil. Ben yalnızca söyledim.
 
Goto ya ihtiyaç duymak için uzman biri olmak gerekmez mi?
PHP'de de goto var ve aynı söylem orada da geçiyor. Eğer bunu kullanacak kadar uzmanlaştıysanız, "Yeterince öğrendiniz" gibi saçma bir söylemdi. :bok1:

Şunu unutmamak lazım; tecrübe edilmemiş bilgi, malumat, yani duyum, dedikodu gibi özümsenmemiş bir şeydir. Malumatlarla bir şeyin özünü öğrenemezsin. Öğretmenlik o kadar kutsanarak anlatılıyor millet başkasının ağzına bakarak hayat sürüyor.

Sürekli başkalarının sunduğu bilgiyi (okumak, video izlemek, takip etmek vb.) tüketmek, insana en fazla belki bir bakış açısı kazandırır ama asla o konuyla ilgili entelektüel bir derinlik kazandıramaz.

Bu nedenle kullanmak gerekiyorsa, hata yapmaktan çekinmemek lazım.

Tabii geliştirdiğin uygulama insan hayatını doğrudan tehdit edecek solunum cihazı, elektrikli araba vb. gibi bir şey değilse... :katil2:
 
İyi niyetinizi anlıyorum. Yalnız klasik C dilinden bahsetmişsiniz.
Bu tarz kodlar altında, C yi kullanmakda pek sıkıntı çekmediğimi düşünüyorum. Kullandığım yapılardır. Nesne tabanlıya daha uzağım ama bunları kullanırım.
İsteğim çalışma tarzı, bu tarz klasik C kodlama ile, uzunca ve karmaşık yoldan yapılabiliyor olsada.
Ben farklı bir şekilde, bahsettiğim tarzda, yapmak istiyorum.
Elinize-gözünüze sağlık, çok zahmet oldu kod yazmışsınız, yalnız gördüğüm kadarı ile, benim isteğimi karşılayamaz gibi duruyor.
Fonksiyonları oluşturmak onları şartlara göre çağırmak değil benim bahsettiğim kısım.

Hala benim yapmak istediğim kısma gelemedik. İyi anlaşılmış olduğuma eminim. Yada şurdan dolayı anlaşılamamış olabilirim belki; while() döngüsü içinde ilgili yere dışarıdan sıçramakdan bahsediyorumya, işte bu dışarısı donanımsal kesmeler (bir nevi fonksiyonlar diyelim) yada kullanıcı tanımlı fonksiyonlar olmak durumunda.
İşte burdaki fonksiyonlardan dolayı iş karıştırılıp, geri dönüş adresi gibi alakasız bir şeyden yada demekki fonksiyon çağırıp kullanmakda sıkıntı çekiliyor diye düşünülmüşde olabilirim belki. Yalnız mesele bunlar değil.
Sanıyorum şu ana kadar cevap verenlerde benim gibi nasıl yapılacağından pek emin değiller. Klasik uzun yöntemlerle yapmam tavsiye edildi sadece.
Yinede ilgilenenelere teşekkürler. Araştırmaya devam edeceğim, vardır illa ki aradığım tarzda yapmanın bir yolu, bulurum herhalde diye düşünüyorum.

Herkese Hayırlı Bayramlar Dilerim.
NOT: Buraya kodlar C derleyiciden kopyalanıp yapıştırıldığında problem olmuyor gibi duruyor. Nasip olursa bir dahakine öyle yaparız.
Hoşcakalın.
 
Stack yapısını biliyor musunuz? Fonksiyon çağrıları nasıl çalışıyor biliyor musunuz?

Fonksiyon arasında sıçrama derken nasıl bir stack değişimi olacak?
 

ckocagil,​

Rica ederim, lütfen siz açıklayıverin, stack yapısını, fonksiyon çağrılarını ve nasıl bir stack değişimi olacağını.
Buralardan elde edilecek verilerle, amaçlanan sonuca nasıl ulaşılabileceğini.
 
Çok spesifik, programlama dilinin size basitçe sunmadığı, sunmaktan da kaçındığı bir şey istiyorsunuz. Bunu yapabilmek için stack neye benzer, fonksiyon çağrıları ve return nasıl çalışır bunları bilmeniz lazım ki setjmp/longjmp gibi gelişmiş özellikleri anlayabilesiniz. Şimdi birisi uğraşıp setjmp/longjmp ile takla atıp istediğiniz şeyi yapsa ben eminim ki %90 ihtimalle beklemediğiniz sorunlarla karşılaşacak ve anlam veremeyeceksiniz.

Bu durumda benim tavsiyem şu ikisinden birini seçmeniz:
1. Ulaşmak istediğiniz esas amaç nedir? Bunu anlatırsanız mutlaka daha mantıklı bir yapı önerilecektir.
2. Bahsettiğim konuları öğrenin, kendiniz uğraşın, takıldığınız yerde sorun.
 
Kod:
void CN_Interrupt() // işlemci giriş pin kesmesi interruptu.
{          if(şartlar1) Atla_1; }

void TIMER1_Interrupt() // işlemci timer kesmesi interruptu.
{          if(şartlar2) Atla_2;}

Double BolmeYap (float sayi1, float sayi2) // kullanıcı tanımlı yazılan fonksiyon.
{          if(şartlar3) Atla_3;}

int main(void)
{  while(1)
        {
Atla_1:
Atla_2:
Atla_3:
}
}

C ilgi alanima girmiyor ama biraz ugrasmisligim var. Bu sekilde bir fonksiyonun icindeki bir satirdan bir baska fonksiyonun icindeki satira goto gibi bir komutla atlamana derleyici izin vermez.

Bu yapi C'ye ters. Eger C degil de ASM ile calisiyor olsaydin derleyici sana karismazdi. Daha dogrusu koyardin bir jmp komutu istedigin yere ziplardin.

Fakat ziplamak yeterli degil. Bir fonksiyona giriste bazi register verileri staga atiliyorsa fonksiyondan cikista da bu register degerlerinin stacktan cekilmesi ya da en azindan stack pointerin degerinin fonksiyona giristeki degerine esitlenmesi gerekir. C yazimda fonksiyondan sonraki { sembolu kodlarin buradan basladigini gosterir. Halbuki { dan once derleyici bazi kodlari yerlestirir ve sen bunlari C program metninde goremezsin. (ASM ciktida gorebilirsin) Ayni sekilde fonksiyonun sonunda yer alan } sembolu artik fonskiyonun bittigini soyler fakat derleyici bu satirdan sonra da bir kac tane asm kod ekler. C yazari bunlari da program metninde goremez.

Ben ordan oraya goto ile atlayacagim derken aslinda bu gorulmeyen ilave kodlari ihlal edecegim diyorsun.

Bu dedigini C de bilemem fakat ASM ile illaki yaparsin. (ASM'de derleyici diger dillerdeki gibi yazara karismaz) Fakat bu yapi son derece tehlikeli olur. O icine girdigin fonksiyonu da o atlayacagin fonksiyonu da avcunun ici gibi bilmen gerekir.

Boyle bir programlama yapisina ihtiyac duyuyorsan kesinlikle yanlis yoldasin.
 
Son düzenleme:
Istedigin yapiyi gotosuz yapmaya yarayacak ipuclarini asagidaki kodlamada bulabilirsin.
exit komutunu, fonksiyonu terk et anlamina gelen C komutu yerine kullandim. Dogrusunu sen yazarsin.
En azindan bu sekilde derleyiciyi kizdirmamis olursun.

Kod:
void CN_Interrupt() // işlemci giriş pin kesmesi interruptu.
{          if(şartlar1) { Atla_1(); Atla2(); Atla3(); exit;}
}

void TIMER1_Interrupt() // işlemci timer kesmesi interruptu.
{          if(şartlar2) (Atla_2(); Atla_3(); exit;}

Double BolmeYap (float sayi1, float sayi2) // kullanıcı tanımlı yazılan fonksiyon.
{          if(şartlar3) {Atla_3(); exit;}


void Atla1()
{
...
}

void Atla2()
{
...
}

void Atla3()
{
...
}

int main(void)
{  while(1)
        {
            Atla_1();
            Atla_2();
            Atla_3();
}
}

Goto icin hep atilip tutulur. Perde arkasindaki sorun, derleyicinin bazi durumlarda C komutlari satir aralarina kullaniciya gostermedigi ilave asm kodlar ekledigi icin kullanici goto ile bunlari farkinda olmadan kolayca ihlal edebilir.

Derleyicinin kalitesi arttikca bu ihlalleri farkedip cozum getirebilir.
 
Çok spesifik, programlama dilinin size basitçe sunmadığı, sunmaktan da kaçındığı bir şey istiyorsunuz. Bunu yapabilmek için stack neye benzer, fonksiyon çağrıları ve return nasıl çalışır bunları bilmeniz lazım ki setjmp/longjmp gibi gelişmiş özellikleri anlayabilesiniz. Şimdi birisi uğraşıp setjmp/longjmp ile takla atıp istediğiniz şeyi yapsa ben eminim ki %90 ihtimalle beklemediğiniz sorunlarla karşılaşacak ve anlam veremeyeceksiniz.

Bu durumda benim tavsiyem şu ikisinden birini seçmeniz:
1. Ulaşmak istediğiniz esas amaç nedir? Bunu anlatırsanız mutlaka daha mantıklı bir yapı önerilecektir.
2. Bahsettiğim konuları öğrenin, kendiniz uğraşın, takıldığınız yerde sorun.
Anladığım kadarıyla, bir kaç yöntemle, aradığım tarzda bir işlem yapılabiliyor gibi gözüküyor. Altdakinin harcinde yapılanlar kafama yatmadı. Sıkıntılı yerler gibi duruyordı. Adreslere işaretçilere müdahaleler falan yapılıyordu.

Daha öncedende elimde ip ucu vardı ve aramalarım hep bunlara çıkıyordu. #include <setjmp.h> LongJump SetJump

İşte bunlar en güvenli olan seçenek olarak görünüyorlar. Bu kütüphanedeki bu ifadelerle işlem yapılmaya çalışıldığında zaten sakıncası görünen yerler büyük ölçüde kendiliğinden güvenle derleyici tarafından aşılmış gibi duruyor. Bu iş için üretildiklerinden gerekli güvenlik önlemlerinide alıyor olmalılar, böyle görünüyor.

Bende sıkıntı çıkartmadılar. İşimi görüyorlar. Goto; Label: dede sıkıntı yaşayabileceğim söyleniyordu, hiç bir zaman yaşamamıştım. Sıkıştığımda kullanıyordum.
Belkide sorunlu kısmı bana denk gelmemişde olabilir. Yalnız ben Goto; Label: ikilisini kullandığım yerin öncesine ve sonrasına en azından C dili tarafında hakim olduğumu düşünüyorum. Derleyici ve ASM kısmından anlamam. C den işi yürütüyorum.

Asıl olayı koparan işi bitiren kısım şurası oldu: Çözüm buradan neticeye ulaştı.
Burada yukarıda çekince olarak verilen kısımlarada açıklamalar getirilmeye çalışılmış.

İlgilenen herkese teşekkür ederim. İşim görüldü. Bu konu benim açımdan kapanmıştır.
 

Forum istatistikleri

Konular
6,154
Mesajlar
105,028
Üyeler
2,558
Son üye
cenkacar

Son kaynaklar

Son profil mesajları

hakan8470 wrote on Dede's profile.
1717172721760.png
Dedecim bu gul mu karanfil mi? Gerci ne farkeder onu da anlamam. Gerci bunun anlamini da bilmem :gulus2:
Lyewor_ wrote on hakan8470's profile.
Takip edilmeye başlanmışım :D ❤️
Merhaba elektronik tutsakları...
Lyewor_ wrote on taydin's profile.
Merhabalar. Elektrik laboratuvarınız varsa bunun hakkında bir konunuz var mı acaba? Sizin laboratuvarınızı merak ettim de :)
Lyewor_ wrote on taydin's profile.
Merhabalar forumda yeniyim! Bir sorum olacaktı lcr meterler hakkında. Hem bobini ölçen hemde bobin direnci ölçen bir lcr meter var mı acaba?
Back
Top