C de neden "goto komutunu kullanmayın" diyorlar ? Ve yazılımcılık tavsiyeleriniz

Başlatan RaMu, 17 Mayıs 2013, 23:33:16

RaMu

  Evet arkadaşlar sorum aslında sadece başlıkda yazdığımdan ibaret, c kullanalar goto komutunu kullanmayı tavsiye etmiyorlar diye biliyorum, evet kullanmayın diyorsanız nedeni nedir, yoksa gönül rahatlığıyla kullanabilir miyiz?

  Şu ana kadar asm ile epey program yazdım, 1-2 aydır ccs kullanıyorum, c de iyi güzel program yazıyorum istediğimi yaptırıyorum ama belkide uzun yoldan veya gereksiz algoritmalarla işi çözüyorum bazen,  bunu önlemek için bazı detaylarıda öğrenmeye çalışıyorum, özellikle öğrenme aşamasında doğru yöntemlerle ilerlemek isterim. Bu yüzden başka hususlardada tavsiyeleriniz varsa açığım.

  Asm de en son FAT dosya sistemli sd kart okuma yazma işlemini yarım yamalak gerçekleştirdim 16f ve dspic30f2010 kullandım, asm de bu noktaya gelene kadar yazdığım programları belşirtmeme gerek yok sanırım.
  CCS de 1 wire lcd kütüphanesi yazdım (idare ediyor ama bazen sapıtıyor), çalıntı bir usb uygulamasını geliştirdim, dokunmatik ekran glcd kullandım, adc falan uyguladım, Serdar Çiçek hocanın kştabındaki uygulamarı inceliyorum.
  Bunları söylememin sebebi, bu işle uzun müddet uğraşmayı düşünüyorum ve yaptıklarımın üstüne ne koyabilirim, nasıl kendimi geliştirmeliyim sorularına karşı fikirlerinizi almak.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

FEHMİ_ASM

        En önemli sebeplerden birisi C'de fonksiyon yapısı olduğu için goto kullanılmaz. Zaten C'de nereye gideceğiniz, fonsiyonu çağıran main fonksiyonu tarafından belirlenir. Çünkü algoritma tümü ile hiyerarşik bir yapı gösterir. Bu, compilerin daha optimizasyonel bir kod üretmesini, anlaşılır bir program yapısı kazanmasını ve kolay debug edilebilmesini sağlar.

    Assembly de (özellikle çok sayıda) kullanmak doğru olmayabilir. Onun yerine alt programlardan return ile dönmek daha mantıklı. Zaten assemblydeki call komutunun karşılığı, c'deki fonsiyon çağrılması ile denk denilebilir.

RaMu

Complier ın optimize kod üretmesi içinse tamam, güzel dikkat etmeliyim o zaman, ayrıca programcının hata yapma olasılığını yükseltmek gibi bir etkisi var mı olur mu?


   Hocam misal şöyle bir durum var, bir menüdeyiz saat ayarı yaptırıyoruz, dakikaya değer giriliyor, değeri kullanıcı 59 dan büyük girdi, bu yüzden dakika ayar yanlış dedik düzgün girsene be adam dedik, ve dakika ayar kısmını tekrar kullnucıya sunuyoruz nasıl yapmalı;
  (aslında bu gotonun aklıma takılmasının sebebi bir arkadaşa program yazarken yardım ediyordum, bu ayar için goto kullanmıştı kullanma dedim, niye dedi öyle diyorlar dedim, dedim ama nedenini bilmediğim için dinletemedim)

Örneği sadece mantığı için öylesine yazıyorum,
dakika:
if  (dakikabutonuna basıldıysa)
{
printf (... dakika değerini giriniz);
(keypad den girilen değeri okuduk dak değişkenine aldık diyelim)
  if (dak>=60) 
{ goto dakika  }

 yok 60 dan büyük değilse buradan artık varsa diğer ayarlara yoksa mesela aldığımız değerleri saat entegresine yazmaya geçiyoruz



Ben bunu goto kullanmadan şöyle yaparım diye düşünüyorum ama buda hoşuma gitmiyor

if  (dakikabutonuna basıldıysa)
{
     d=0;    //d değişkenini 0 yap
     while (d==0)
    {
     printf (... dakika değerini giriniz);
     (keypad den girilen değeri okuduk dak değişkenine aldık diyelim)
         if (dak<=60) 
        { d=1  }                     // artık doğru dakika değeri alındı while döngüsünü tekrar işleme
      }

}
   yok 60 dan büyük değilse buradan artık varsa diğer ayarlara yoksa mesela aldığımız değerleri saat entegresine yazmaya geçiyoruz


Yoksa bu işi ek bir d değişkeni kullanmadan veya daha basit bir şekilde nasıl çözeriz.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

alorak

Aşağıdaki alıntı belki tatmin edebilir bu düşüncede.

Alıntı Yapgoto yapısıyla gelen esneklik, ilk bakışta oldukça güzel görünüyor. Ancak goto için birçok kaynak, "ya hiç kullanmayın ya da olabildiğince az kullanın" demektedir.

Okunup, anlaşılması zor ve üzerinde çalışılması güç bir koddan, herkesin uzak durması gerekir. İngilizce'de, karman çorman koda, "spagetti kod" adı verilmiştir. goto deyimi, kodunuzun spagetti koda dönüşmesine neden olur. Çünkü program akışının takibini zorlaştırıp, kodun okunabilirliğini azaltır. Diliyorsanız, goto deyimini kullanabilirsiniz. Ama zorunlu kalmadıkça kaçınmak en iyisi...

kaynak: http://www.cagataycebi.com/programming/c_programming/c_programming_5.html
Özgürlük için...

Analyzer

Selam,

C nin yapısından tutun da kod üretme kısmına kadar bir çok sebepten dolayı goto kullanımı tavsiye edilmez. Goto ile dallanacağınız kısmı bir fonksiyon içerisine alır, o fonksiyonu çağırırsınız. Zaten alışkanlık kazandığınızda siz de goto sevmeyeceksiniz. Üniversitedeki hocamız, goto gördüğü anda kağıdı kırmızı kalemle diagonal çizerdi.

Analyzer
Üşeniyorum, öyleyse yarın!

FEHMİ_ASM

Alıntı yapılan: RaMu - 18 Mayıs 2013, 00:07:58
Complier ın optimize kod üretmesi içinse tamam, güzel dikkat etmeliyim o zaman, ayrıca programcının hata yapma olasılığını yükseltmek gibi bir etkisi var mı olur mu?

     Elbette olmaz. Program daha kolay okunabilir olduğu için hata yapma oranı azalır.
     Goto bir uzak dallanma komutudur. Hemen peşindeki komutları işlemeksizin ve geri dönmeksizin atladığı için risklidir. O amaçla kullanılması önerilmez.

    Birinci örnekte dakika adında ayrıca bir fonksiyon oluşturabilir, birinci fonksiyondan dönen değeri dakika fonksiyonunda kullanabilirsiniz.

MrDarK

Goto ile zaten bir fonksiyondan diğer bir fonksiyona sıçrayamazsın ASM'deki gibi ;

2000 küsür satırlık bir CCS kodumdan altıntı yapıyorum hocam ; bu gördüğün bölge sadece main blogu oda ayarlarla dolu zaten büyük kısmı :D

void main()
{

   setup_adc_ports(ALL_ANALOG);
   setup_adc(ADC_CLOCK_DIV_8);
   disable_interrupts(GLOBAL);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   // TODO: USER CODE!!
   glcd_init(ON); 
//  animasyon();
  glcd_showimage1();
  delay_ms(4000);
  glcd_init(ON);
  sayi=1;
  buton=0;

while(1)
{
   adc_topla();
   buton=buton_tara();
   buton_isle(buton);
   karar_ver();
}
}


Anlatmak istediğim o ki 2000 küsür satıra sadece fonksiyon kullanarak geldim ayrıca her fonksiyon kendi içinde fonksiyonlara ayrılıyor tıpkı bir ağacın dalları gibi.

Bu sayede hata olan noktaları temizleyip düzeltmek kolay oluyor.

Bir avantajı daha var kullandığın her fonksiyonu hiç değiştirmeden yada ufak eklentilerle başka programlarda çok rahat geçmiş kütüphane şeklinde hazırladığın fonksiyonları kullanmakta ayrı bir keyif veriyor insana :)
Picproje Eğitim Gönüllüleri ~ MrDarK

engineer

Merhaba, C'de her fonksiyon tamamlandıktan sonra bir üst fonksiyona geri döner. En üst fonksiyon olan main() yada windows uygulamaları için WinMain() tamamlandıktan sonra program sonlanır ve varsa işletim sistemine bir parametre ile geri döner. Her fonksiyon çağrıldığında yığında o fonksiyon için yer ayrılır ve iç içe fonksiyonlar için bu dallanıp budaklanır. İyi bir c programcısı her fonksiyonun geri dönüş değerini ve sırasını takip edebilmelidir. Goto kullanımında yığında yer ayrılmaz, doğrudan belirtilen etikete dallanma sağlanır ve fonksiyonlar neredeyse göz ardı edilir. Goto ile dallanılan yerdeki komutlar icra edildikten sonra program akışına devam eder ve ilk fonksiyon bloğu sonlandığında yığına gidip dönmesi gereken yeri ve parametreleri yığından almak istiyecektir. İşte bu noktada bir fatal error oluşabilir :) siz daha önce goto'nun içinde bulunduğu bir fonksiyondan bir üst yada daha üst bir fonksiyon içerisinde bir yere dallandıysanız, o fonksiyon geri dönüşte yığındaki en son girdiyi çekecektir ancak bu çektiği kendi bilgisi değil alt fonksiyonunun bilgisidir. Basit programlarda goto'nun takibi kolay olabilir ancak program karmaşıklaştığında goto'nunda diğer fonksiyonlarında takibi zorlaşır. Goto kullanmak bu yüzden tehlikelidir. Şu an aklıma sadece bu senaryo geldi, daha farklı senaryolarda oluşabilir..

RaMu

  fehmi_asm  Birinci örnekte dakika adında ayrıca bir fonksiyon oluşturabilir, birinci fonksiyondan dönen değeri dakika fonksiyonunda kullanabilirsiniz. bunu çözemedim, nasıl yani?

   Arkadaşlar teşekkür ediyorum değindiğiniz noktalar önemli bilgiler içeriyor. Yani bende kod yazarken işlemi en kısa sürede yapacak, en az kod satırı kullanacak (derlendiğindede), okuması debug işi kolay, modüler-başka programlarda kullanılabilecek şekilde kod yazmanın gerektiğini düşünüyorum, bunu herhalde kod yazdıkça ve güzel yazılmış örnek kodları inceledikçe öğreneceğiz, yazdığım örnekleride arada eleştirebilirseniz sevinirim örnek üzerinden gitmek daha kolay olur diye düşündüm.

    MrDark evet uzun kodlar adamı çileden çıkarabiliyor, bu yüzden işi kolaylaştıracak yöntemleri kullanmalı, şimdi buna örnek söyleyebilmeme zor ama misal birçok duruma karşı birçok cevap verecek, menüleri ayarları olan, dışarıdan gelen verilere, buton - sensör vs. göre çeşitli çıkışlar üreten bir program yazdığımızda, if içinde 10 tane if, while içinde while lar ifler do lar ile karşılaşıyorum bunlarda programı karıştıryor, bu if nerede başlamıştı bu kapanan parantez hangi döngümnündü diye aranıp duruyorum, bakalım çözeceğiz artık, bulacağız doğru yolu :)


  Birde böyle olabilir diye düşünüyorum,

if  (dakikabutonuna basıldıysa)     //  dakika ayar butonuna basıldıysa ayar fonksiyonuna girecek
{

    do                                       // dak değeri ne olursa olsun do içi en az bir defa işlenecek
    {
     printf (... dakika değerini giriniz);
     (keypad den girilen değeri okuduk dak değişkenine aldık diyelim)

     }while(dak>=60);              // kullanıcının girdiği dak değeri 60a eşit veya
                                      // büyükse do kısmı (dakika ayar)tekrarlanacak, 
                                      //küçükse değer doğru-while içi yanlış,do-while dan çıkılacak
 }

  buradan artık varsa diğer ayarlara yoksa mesela aldığımız değerleri saat entegresine yazmaya geçiyoruz 
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

bezgin

Sorunuzu biraz geç gördüm fakat yanıtlamak isterim. İlk olarak sizinde kendizi ifade ettiğiniz gibi bende kısaca kendimi ifade edeyim ilk ticari programımı 1985 yılında satmıştım ( evet yazım hatası yok 28 yıl evvel gerçi bana dün gibi geliyor) bu sitedeki arkadaşların ortalama yaşı bana göre çok genç olduğundan sizide öyle varsayıyorum bu sorunuz beni oldukça memnun etti. Şimdi birçok programcı kelimeleri geçtim kısaltmaları bilmekle övünüyorlar. Bizim zamanımızda bir dizinin sıralama methodu (algoritması) olarak yaklaşık 20 çeşidinide peyderpey öğrenmiştik. Bence algoritma programcının kendisine en kolay yolu seçmesiyle başlar yok goto kullanma yok hatırlatıcı notlar yaz bana göre bunlar hikaye ben fazla kasmayayım ama 20 sene önce yazdığım kodu bile görünce hatırlarım. Benden sana tavsiye bunu muhakkak araştır bubble sort ile quick sort arasındaki farkı anladığında sorunun karşılığını tam olarak öğreneceksin. Ben program yazarken her programın optimum olacak diye bir kaide olmadığından çoğu kez ezberden bubble sort yazarım gider ama bu fonksiyon çok kullanılacaksa hızdan düşmemek için quick sort yazmayı tercih ederim işte hikaye olmayan kısmı bu. Gelelim goto meselesine; şimdiki bir kısım  c programcısı veya geniş tutalım c,c+,c++,c#  bu dillerin sosyete programcılığını yapıyorlar, eskiden de pascal sosyetesi vardı  neyse; ezberden aman goto kullanma etiğini devam ettiriyorlar. Acizane benim yorumum programlama dilinin recursif olup olmadığı ile ilgilidir. Ne zaman ki pascal çıktı programlama dünyasına recursif niteliğini koydu ( çoook iyide oldu ) goto komutu istenmeyen komut oldu. Şimdi hepimiz biliyoruz ki goto komutu en temel komuttur ve kullanılır sebebine gelince diller anası assembler değilmi tüm derleyiceler (c,pascal,fortran,basic ve sülaleleri ) vardıkları noktada barnch komutlarında goto yokmu var. İşin komiği bir zamanlar while..do, do..until komutlarında da gizli if var diye tü kaka olmuştu  ( oldum olası bende pek sevmem bu iki komutu) . Programcının eliti bırakınız goto komutunu if then else komutunu bile çok kullanmamalıydılar. Bir zamanlar ODTÜ'de sıralı bir dizide var olan bir sayının kaçıncı sırada olduğunu if..then..else komutunu kullanmadan yapınız sorusu oldukça meşhurdu.  İlk arabamı aldığımda bana o zamanlar çok moda olan tubeless lastik aldırmışlardı abi bunu al lastik patlasa bile baya yol gidersin diye ya baya yol ne kadar diye amma kafa yormuştum herkese sordum en sonunda bir abi lastiğe küçük bir çivi girse ve sende çıkarmaz isen  lastikçiye kadar gidersin ama delik büyükse bir yere gidemezsin demişti. Bence Goto komutuda bu değerdirmeye giriyor. Ticari program yapmışsın oldukça iyide satıyor içindeki goto sayısından kime ne veya kim kime maddi kazanç beklediği bir programın kaynağını gösterir ki? ha 3 satırda yazmışsın ha 3000 satırda bunlar işin hikayesi. Benden sana tavsiye aman goto kullanma diyenlere sor bakalım assembler'da NOP komutu ne işe yarıyormuş. Cevaba göre işim sosyetesindemi değilmi anında anlaşılır. Assembler'da program yazabilen bir arkadaş değişik projeler yaptığında Algoritma bigisi ister istemez yükselecektir. Bir projede hafıza yetmeyecek , diğerinde hız yeterli olmayacak, diğerinde real time olması gerekecek bunları aşmayı başardıkçada eskiye nazaran ne kadar çok bilgilendiğini zaten kendin anlayacaksın. Lafa bakarmısın az kullanman veya hiç kullanmaman gerekir ne bu ya ilaç mı, üç beyazdan birimi hani bilgisayarda sadece sıfır veya bir vardı. Ben çok kullanınca ... problemi olurmuş o benim değil derleyicinin problemidir. Stack problemi üzerinde duranlar için Faktöriyel Hesaplama programını recursif yazıp denemelerini tavsiyede ederim çok büyük bir sayı girildiğinde bile nasıl çalışıyor görülür tamam bu ... derleyisinde  olmadı veya yavaş  o zaman LISP'te yazıp farka bakabilirler. Program uzun olunca anlaşılmazmış ne o mikrokontroler'a muhasebe programımı yazıyoruz. Bana 100 satırlık algoritmik özelliği olan bir program göstersinler veya quick sort programının satır sonlarına bir açıklama yazsınlarda göreyim. Ben bunca yıllık mesleki yaşamımda 50 satırı aşan algoritma görmedim.

Dakika alma işine gelince ben olsam ilk tuş basıldığında 6,7,8,9 tuşlarından biri ise kaale almam beklerim, ikinci tuşu ise tamamen serbest bırakırım.

"İnsan başkasının yumruğunu yemeden, kendi yumruğunu Balyoz zannedermiş.."  özet olarak bubble sortu yapan  abi  quick sort'u görünce bence biraz imrenmiştir. Aslında bunca uzun yazıyı okuyan varsa hakikaten teşşekkür ederim.
iyi çalışmalar
Qaravul

Not: Yukarıda yazdıklarımdan lütfen forumdaki arkadaşlar alınmasın kimseyi yermek gibi bir niyetim yoktur. 28 yıllık tecrübeme dayanarak yaşadıklarımın özetini yazdım. Tüm programcı gençlerin kimsenin iyisin, kötüsün demesine aldırmaksızın projelerini tamamlasınlar ve kendi değerlerini kendileri biçsinler. Hatasız çalışan programı yazdığınızda iş biter.

2.not :yazım hatası yapmışım düzeltmeme yardımcı olmanızdan dolayı ahmets arkadaşa teşşekkür ederim.

t2

Alıntı Yapilk ticari programımı 1985 yılında satmıştım

yazı uzun, sıkıcı. sadece buraya kadar okudum. tebrik ederim sizi

ahmets

"Yeni" üye bezgin'in yazısını okudum.
Katıldığım yerleri var, anlamsız gelen yerleri var.

Son cümleye takıldım.
Alıntı yapılan: bezgin - 21 Haziran 2013, 10:03:43
... Hatasız çalışan programı yazdıklarında iş biter.

Hatasız çalışan program yazıldığında iş bitmez. Bu yüzden goto kullanılması tavsiye edilmez.
İsterseniz bana bir tane hatasız yazdığınız programın çalışan exe'sini gösterin. Kullandığınız goto'ların nasıl sorunlara yol açabileceğini örnekleyerek açıklamaya çalışayım.

CoşkuN

Burası demokratik bir ülke kardeşim isteyen istediğini kullanır :)
Şaka bir yana bu tür "kullanılmamalı" tarzı önermeler birer tavsiyeden ibarettir ve yazılım mühendisliğinde ortak olarak karşılaşılan problemler sonucu ortaya atılmıştır. Ama biz her seferinde neyi tartışıyoruz orayı anlamıyorum.

bocek

@bezgin kardeş programlarını da, mesajını yazdığın tarzda yazıyorsan bir çok sorunlara gebe olması muhtemel.
Mesela 'enter'a basmayı pek sevmiyorsun (az sayıda satır ile işi bitirmek), ODTÜ'deki sıralama algoritmasından bahsederken birden "tubeless lastik" mevzusuna atlıyorsun (goto kullanımı) vs.
Programın çalışıyor olması sorun çıkarmayacağı anlamına gelmiyor elbette. 10 yıldan fazladır binlerce kişinin kullandığı bir PC programı bunca yıldan sonra işgüzarın birinin lüzumsuz bir girişi sonucu hata verebiliyor. Düşünün binlerce kişi kullanmış bir şey olmamış, 'o' şahıs kullanmış hata vermiş:) Oluyor böyle şeyler. Onun için de 'elit' kesimin tecrübelerine hor gözle bakmamak lazım.
Kusura bakma tecrübene ve çıkardığın işlere saygı duyarım ama bu goto mevzusuna bu kadar atarlanmak ta gereksiz bence.
İsteyen kullansın, ben kullanmam. Hiç kullanmadım daha.
1 ya da 0. işte 'bit'ün mesele..

mufitsozen

Alıntı YapSorunuzu biraz geç gördüm fakat yanıtlamak isterim. İlk olarak sizinde kendizi ifade ettiğiniz gibi bende kısaca kendimi ifade edeyim ilk ticari programımı 1985 yılında satmıştım ( evet yazım hatası yok 28 yıl evvel gerçi bana dün gibi geliyor)

Sayin @bezgin, bende ilk programimi 1974 senesinde yazdim ve bir suru goto vardi (yazim hatasi yok, ama bana dun gibi gelmiyor maalesef!).

Ama 1984 senesinden beri hataya yol acan ve anlasilmasi guc durumlara sebep olmasindan dolayi cok nadiren goto kullaniyorum.

Nadiren goto kullanmanin avantaj sagladigi durumlar olabilir ama butun modern dillerde goto kullanmadanda daha kolay yazilan ve anlasilan programlar yazilabilir, bu bir egitim meselesidir. (yani egitim sart!)  :P

bu arada ODTU elektrik elektronik mezunuyum, ve ogrenim surem boyuncada ODTU bilgisayar Merkezinde Asistan ogrenci olarak calistim.

Fakat bu tip bilgilerin hicbir anlami yok, belkide su anda 15 yasinda bir lise ogrencisi benden daha iyi/cabuk/hizli/dogru/kompakt program yazabiliyordur!

mesaj birleştirme:: 21 Haziran 2013, 16:16:23

Bu konuda daha "seviyeli" yada "teknik" bir tartisma yapmak isteyenler, kisa bir ozet icin Microsoft Press'den "Code Complete" kitabinin 17.3 bolumune bakabilir.

Benim nacizane fikrimi sorarsaniz, bu kitap zaten programciyim diyen herkesin, kutuphanesinde bulunmasi ve bastan sona değilse bile, programlama ile konularda ilk olarak bakilacak referans kitaplardandir.

'goto kotudur' diyenlerde 'goto kullanilabilir' diyenlerde yuzeysel tartismalar yapmak yerine en azindan bu kitaba basvurabilirler.

bu arada bu konunun ilk defa tartisma konusu olmasi 1968 yilinda Edsger Dijkstra nin ACMde yazdigi "Go To Statement Considered Harmful" mektubu ile baslar!

Bu konuya bir aciklama olmasi bakimindan bahsi gecen kitapdan bir bolumu asagiya ekliyorum.

Alıntı YapIn some cases, the goto can result in faster and smaller code. Knuth's 1974
article cited a few cases in which the goto produced a legitimate gain.
Good programming doesn't mean eliminating gotos. Methodical decomposition,
refinement, and selection of control structures automatically lead to goto-free
programs in most cases. Achieving goto-less code is not the aim, but the
outcome, and putting the focus on avoiding gotos isn't helpful.


Decades' worth of research with gotos failed to demonstrate their harmfulness.
In a survey of the literature, B. A. Sheil concluded that unrealistic test
conditions, poor data analysis, and inconclusive results failed to support the
claim of Shneiderman and others that the number of bugs in code was
proportional to the number of gotos (1981). Sheil didn't go so far as to conclude
that using gotos is a good idea—rather that experimental evidence against them
was not conclusive.
Finally, the goto has been incorporated into many modern languages including
Visual Basic, C++ and the Ada language—the most carefully engineered
programming language in history. Ada was developed long after the arguments
on both sides of the goto debate had been fully developed, and after considering
all sides of the issue, Ada's engineers decided to include the goto.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.