{"id":305,"date":"2015-02-22T11:49:53","date_gmt":"2015-02-22T09:49:53","guid":{"rendered":"http:\/\/ozenozkaya.com\/blog\/?p=305"},"modified":"2018-01-10T12:27:24","modified_gmt":"2018-01-10T10:27:24","slug":"gomulu-sistemler-25-gomulu-c-isaretciler-2","status":"publish","type":"post","link":"http:\/\/ozenozkaya.com\/blog\/?p=305","title":{"rendered":"G\u00f6m\u00fcl\u00fc C &#8211; 14 : \u0130\u015faret\u00e7iler 2"},"content":{"rendered":"<p>\u0130\u015faret\u00e7iler (pointers) ba\u015fl\u0131kl\u0131 yaz\u0131mda konuyla ilgili g\u00fczel bir girizgah ve temel atma merasimi tertip\u00a0ettik. \u015eimdi, i\u015faret\u00e7ilerle ilgili daha ileri konulara de\u011finmenin tam s\u0131ras\u0131. \u0130\u015fin asl\u0131 i\u015faret\u00e7ilerin kullan\u0131m alanlar\u0131 \u00e7ok \u00e7ok geni\u015f. Tilkiler normalde yaln\u0131z dola\u015f\u0131r ama i\u015faret\u00e7iler de\u011fince akl\u0131mda bin bir tilki s\u00fcr\u00fc halinde dola\u015f\u0131yor. Hepsini burada yazmak \u00e7ok m\u00fcmk\u00fcn m\u00fc bilmiyorum ancak, elimden geldi\u011fince yazmaya \u00e7al\u0131\u015faca\u011f\u0131m.<\/p>\n<p>Efendim \u00f6zellikle belle\u011fi etkin kullanma noktas\u0131nda, i\u015faret\u00e7iler ziyadesiyle \u00f6nemli bir fakt\u00f6r oluyor.\u00a0Bu sebepledir ki g\u00f6m\u00fcl\u00fc programlama yapacak yi\u011fitlerin i\u015faret\u00e7ilerin suyunu s\u0131kmas\u0131 gerekmektedir. Mevzunun \u00f6z\u00fct\u00fc yine ayn\u0131 olsa da, her bir kullan\u0131m alan\u0131ndan al\u0131nacak say\u0131s\u0131z ibretler oldu\u011fundan, farkl\u0131ca \u00f6rnekler \u00fczerinden i\u015faret\u00e7ileri inceleyemeye \u00e7al\u0131\u015faca\u011f\u0131m. Yine de eksik kalan bir kullan\u0131m alan\u0131 oldu\u011funu d\u00fc\u015f\u00fcn\u00fcyorsan\u0131z, yorum olarak ekleyebilirsiniz.<\/p>\n<p>Bu yaz\u0131y\u0131 okumay\u0131 bitirdi\u011finizde varaca\u011f\u0131m\u0131z noktada iki yol var.<\/p>\n<ol>\n<li>Bu \u015feyler sizler i\u00e7in yeni \u015feyler ise, bunlar\u0131 sindirdi\u011finizde o \u00e7ok korkulan i\u015faret\u00e7iler konusunda harbici bir uzman olmu\u015f olacaks\u0131n\u0131z.<\/li>\n<li>Bu \u015feylerin tamam\u0131n\u0131 zaten biliyorsan\u0131z, \u00a0zaten bir uzmans\u0131n\u0131z. L\u00fctfen\u00a0siz de blog yaz\u0131n, haber edin biz de takip edelim yeni \u015feyler \u00f6\u011frenelim \ud83d\ude42<\/li>\n<\/ol>\n<p>Neyse \u015fimdi derin bir nefes al\u0131p ba\u015flayal\u0131m. Zira bu konular ciddi konular. Tek nefes yetmeyecek ama her nefesi derin almakta faydalar var.<\/p>\n<p><strong>Mutlak Adres \u0130\u015faret\u00e7ileri (Pointers to Absolute Addresses)<\/strong><\/p>\n<p>\u0130\u015faret\u00e7ilerin genel felsefesini bir \u00f6nceki yaz\u0131da konu\u015ftuk. Genelde bir tipteki bir i\u015faret\u00e7i, genelde ayn\u0131 tipteki bir de\u011fi\u015fkeni i\u015faret ediyordu. Peki ya bir i\u015faret\u00e7i, sabit bir adresi i\u015faret ederse?<\/p>\n<p>Hmm. \u0130yi g\u00fczel, etsin de niye etsin? G\u00f6m\u00fcl\u00fc sistemlerde g\u00f6receksiniz ki, \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131z platformun (mikrokontrol\u00f6r, fpga, SoC, vs) sabit bir bellek haritas\u0131 var. Yani ROM,RAM, \u00e7evreseller filan hep sabit adreslerden ba\u015flar. Do\u011fal olarak, register&#8217;lar da sabit adreslere sahiptir.<\/p>\n<div class=\"su-box su-box-style-noise\" id=\"\" style=\"border-color:#127ab2;border-radius:3px;\"><div class=\"su-box-title\" style=\"background-color:#45ade5;color:#FFFFFF;border-top-left-radius:1px;border-top-right-radius:1px\">Register Ne Ki?<\/div><div class=\"su-box-content su-u-clearfix su-u-trim\" style=\"border-bottom-left-radius:1px;border-bottom-right-radius:1px\">\u0130lk defa duyanlar i\u00e7in register; g\u00f6m\u00fcl\u00fc sistemde donan\u0131m\u0131n izin verdi\u011fi baz\u0131 donan\u0131msal konfig\u00fcrasyonlar\u0131 saklamak i\u00e7in kullan\u0131lan bellek alan\u0131d\u0131r. \u00d6rne\u011fin bir pinin giri\u015f olarak m\u0131, \u00e7\u0131k\u0131\u015f olarak m\u0131 konfig\u00fcre edildi\u011fi bir regsiter&#8217;da tutulur. T\u00fcrk\u00e7e&#8217;ye &#8220;k\u00fct\u00fck&#8221; olarak \u00e7evrilmi\u015ftir ancak bu \u00e7eviri k\u00fct\u00fck gibi bir \u00e7eviri oldu\u011fundan, ben d\u00fczg\u00fcn bir \u00e7eviri \u00e7\u0131kana kadar register diyece\u011fim.\u00a0<\/div><\/div>\n<p>Register&#8217;lar sabit adreslere sahiptir dedik. \u00d6yleyse biz bunlara eri\u015firken yani buralar\u0131 i\u015faret ederken asl\u0131nda sabit adresleri i\u015faret edece\u011fiz. Bu vesile ile\u00a0mutlak adresleri i\u015faret eden i\u015faret\u00e7ilerin nerede kullan\u0131laca\u011f\u0131 hususunu apa\u00e7\u0131k bir \u015fekilde g\u00f6zler \u00f6n\u00fcne sermi\u015f olduk.<\/p>\n<p>\u00d6yleyse \u015fimdi bir \u00f6rnek \u00fczerinden gidelim. Diyelim ki bizim mikrokontrol\u00f6r\u00fcn \u00fc\u00e7 tane versiyonu var: A,B,C. Ve elimizdeki mikrokontrol\u00f6r\u00fcn 0xC0FFE nolu bellek adresinde bu k\u0131ymetli bilgi yaz\u0131yor. Bu bilgiyi nas\u0131l okuyaca\u011f\u0131z? Hemen yazal\u0131m!<\/p>\n<pre class=\"lang:c decode:true\">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\n#define REG_DEVICE_TYPE_ID_CHAR (0xC0FFE)\r\n\r\nint32_t main()\r\n{\r\n  int8_t *pRegDevTypeIdChar = (int8_t*)REG_DEVICE_TYPE_ID_CHAR;\r\n  \r\n  printf(\"Device Type ID Char = %c\", *pRegDevTypeIdChar);\r\n\r\n  return 0;\r\n}<\/pre>\n<p>Notasyon ve kod gayet temiz diye d\u00fc\u015f\u00fcn\u00fcyorum. Peki diyelim ayn\u0131 mikrokontrol\u00f6r\u00fcn 0xFACE adresinde bulunan register da mikrokontrol\u00f6r\u00fc ba\u015flatmak i\u00e7in olsun. Bizim mikrokontrol\u00f6r\u00fc ba\u015flatmak i\u00e7in ille de 0xFACE adresine &#8216;S&#8217; yazmak gereksin. Onu nas\u0131l yapard\u0131k?<\/p>\n<pre class=\"lang:c decode:true\">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\n#define REG_DEVICE_START_CMD (0xFACE)\r\n#define CMD_DEVICE_START ('S')\r\n#define CMD_DEVICE_PAUSE ('P')\r\n#define CMD_DEVICE_RESET ('R')\r\n\r\nint32_t main()\r\n{\r\n  int8_t *pRegDevStartCmd = (int8_t*)REG_DEVICE_START_CMD ;\r\n \r\n  \/\/Start device by writing relevant register to 'S'\r\n  *pRegDevStartCmd = CMD_DEVICE_START;\r\n  \r\n  \/\/...\r\n  \r\n  \/\/Pause Device by writing relevant register to 'P'\r\n  *pRegDevStartCmd = CMD_DEVICE_PAUSE ;\r\n\r\n  return 0\r\n}<\/pre>\n<div class=\"su-box su-box-style-noise\" id=\"\" style=\"border-color:#127ab2;border-radius:3px;\"><div class=\"su-box-title\" style=\"background-color:#45ade5;color:#FFFFFF;border-top-left-radius:1px;border-top-right-radius:1px\">\u00d6NEML\u0130 NOT!<\/div><div class=\"su-box-content su-u-clearfix su-u-trim\" style=\"border-bottom-left-radius:1px;border-bottom-right-radius:1px\">NOT: Yukar\u0131daki kodu bilgisayar\u0131n\u0131za at\u0131p \u00e7al\u0131\u015ft\u0131rmay\u0131n diye return 0&#8217;dan sonraki virg\u00fcl\u00fc sildim ve sistemin \u00f6zellikle derleme hatas\u0131 vermesini istedim. Bilgisayar\u0131m\u0131zda 0xFACE alan\u0131 korunan, \u00f6zel bir bellek alan\u0131 olacakt\u0131r. Yukardaki koddan yaln\u0131zca ibret \u00e7\u0131kar\u0131n\u0131z, kodu bilgisayar\u0131n\u0131zda \u00e7al\u0131\u015ft\u0131rman\u0131za bence pek gerek yok \ud83d\ude42 \u00c7al\u0131\u015ft\u0131rsan\u0131z da zaten yazma korumas\u0131 oldu\u011fundan kod donacakt\u0131r ve i\u015fletim sistemi taraf\u0131ndan sonland\u0131r\u0131lacakt\u0131r.<\/div><\/div>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi muhteremler, sabit adresleri i\u015faret eden i\u015faret\u00e7ileri s\u0131kl\u0131kla kullanaca\u011f\u0131z. \u015eu ana kadar bellekteki bilgiyi hep int8_t olarak anlamland\u0131rd\u0131k. Ger\u00e7ek\u00e7i durumlarda genelde konfig\u00fcrasyonlar mikrokontrol\u00f6r register&#8217;lar\u0131nda struct gibi saklan\u0131r. O sebeple struct&#8217;\u0131 nas\u0131l sabit bir adrese g\u00f6steririz onu d\u00fc\u015f\u00fcnmekte faydalar var.<\/p>\n<p>Benzer bir mevzu ama, registeri do\u011frudan i\u015faret eden bir etiket de a\u015fa\u011f\u0131daki gibi tan\u0131mlanabilir:<\/p>\n<pre class=\"lang:c decode:true\">#define NVIC_ST_CTRL_R          (*((volatile uint32_t *)0xE000E010))\r\n#define NVIC_ST_RELOAD_R        (*((volatile uint32_t *)0xE000E014))\r\n#define NVIC_ST_CURRENT_R       (*((volatile uint32_t *)0xE000E018))\r\n#define GPIO_PORTF_DATA_R       (*((volatile uint32_t *)0x400253FC))<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Fonksiyon \u0130\u015faret\u00e7ileri (Function Pointers)<\/strong><\/p>\n<p>Fonksiyon i\u015faret\u00e7ilerinin bir \u00f6rne\u011fini asl\u0131nda karar yap\u0131lar\u0131 yaz\u0131s\u0131nda vermi\u015ftim ama pek a\u00e7\u0131klamam\u0131\u015ft\u0131m. \u015eimdi bu vesileyle bu \u00f6nemli konuyu da bir nebze daha peki\u015ftirme f\u0131rsat\u0131 bulmu\u015f olaca\u011f\u0131z.<\/p>\n<p>C dilinde fonksiyonlar da esasen bir nevi de\u011fi\u015fkendir. Ancak fonksiyonlar, daha \u00f6nceden de detayl\u0131ca a\u00e7\u0131klad\u0131\u011f\u0131m\u0131z \u00fczere biraz pahal\u0131 de\u011fi\u015fkenlerdir. Bu vesileyle bedeli \u00f6denerek tan\u0131mlanm\u0131\u015f fonksiyonlar\u0131n, ikinci a\u015famada i\u015faret edilmesi ihtiyac\u0131 do\u011fmaktad\u0131r. Hemen \u00f6rne\u011fimizi hat\u0131rlayal\u0131m.<\/p>\n<pre class=\"lang:c decode:true\">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n \r\n#define STATE_DEMO_LOOP_CNT    (10)\r\n \r\ntypedef void (*myStateHandler) (void);\r\n \r\ntypedef enum\r\n{\r\n  E_STATE_NONE=0,\r\n  E_STATE_1,     \r\n  E_STATE_2,\r\n  E_STATE_3,\r\n  E_STATE_4,\r\n  E_STATE_LAST\r\n}E_STATES;\r\n \r\nmyStateHandler myStateList[E_STATE_LAST];\r\nE_STATES e_state;\r\n \r\n \r\nvoid STATE1_HANDLER (void)\r\n{\r\n     printf(\"State1n\"); \r\n     e_state = E_STATE_3;  \r\n}\r\n \r\nvoid STATE2_HANDLER (void)\r\n{\r\n     printf(\"State2n\"); \r\n     e_state = E_STATE_4;  \r\n}\r\n \r\nvoid STATE3_HANDLER (void)\r\n{\r\n     printf(\"State3n\"); \r\n     e_state = E_STATE_2;  \r\n}\r\n \r\nvoid STATE4_HANDLER (void)\r\n{\r\n     printf(\"State4n\"); \r\n     e_state = E_STATE_1;  \r\n}\r\n \r\n \r\nvoid Init()\r\n{\r\n    myStateList[E_STATE_1] =  STATE1_HANDLER;\r\n    myStateList[E_STATE_2] =  STATE2_HANDLER;\r\n    myStateList[E_STATE_3] =  STATE3_HANDLER;\r\n    myStateList[E_STATE_4] =  STATE4_HANDLER;\r\n    e_state = E_STATE_1;\r\n}\r\nint main()\r\n{\r\n    uint8_t bCnt;\r\n    Init();\r\n    \r\n    for(bCnt=0;bCnt&lt;STATE_DEMO_LOOP_CNT;bCnt++)\r\n    {\r\n        myStateList[e_state]();    \r\n    }\r\n    \r\n    while(1); \/\/stop here\r\n    return 0;\r\n }<\/pre>\n<p>\u00d6rne\u011fimiz asl\u0131nda ball\u0131 kaymak. Neden? \u00c7\u00fcnk\u00fc fonksiyon i\u015faret\u00e7isini tan\u0131mlamak ile yetinmemi\u015fiz, o \u00f6zel i\u015faret\u00e7i tipini bir de typedef ile tan\u0131mlam\u0131\u015f\u0131z ki, ihtiyac\u0131 olan herkes bu yeni tipten faydalans\u0131n. Bir nevi hayrat yakla\u015f\u0131m\u0131 olmu\u015f. Neyse&#8230; Fonksiyon i\u015faret\u00e7isi a\u015fa\u011f\u0131daki gibi tan\u0131mlanm\u0131\u015f:<\/p>\n<pre class=\"lang:c decode:true\"> void (*myStateHandler) (void);<\/pre>\n<p>Bu yaz\u0131m tipi sabit. &#8220;donusTipi (*isim) (argumanlar)&#8221; \u015feklinde bir kal\u0131b\u0131m\u0131z var. Fonksiyon i\u015faret\u00e7isi b\u00f6yle tan\u0131mlan\u0131yor. Peki buradaki hikmeti ne bu i\u015faret\u00e7inin? Switch-case yerine bunu kulland\u0131k tamam, ayn\u0131 \u015fekilde de \u00e7al\u0131\u015ft\u0131 ama bu mevzunun alt\u0131nda yatan felsefe ne? Nesneye dayal\u0131 programlamada polymorphism yani \u00e7ok \u015fekillilik dedi\u011fimiz mevzun\u0131n C dili ile ger\u00e7eklenmesi asl\u0131nda bu. Yukar\u0131daki kodda her durummun bir durum fonksiyonu var. Bu fonksiyonun \u015fekli \u015femali hepsi i\u00e7in ortak. Ve hangi durum olursa, o durumun fonksiyonu \u00e7a\u011f\u0131r\u0131l\u0131yor. Her biri ayn\u0131 \u015fekilde \u015femalde bu fonksiyonlar\u0131n, hepsini ayn\u0131 i\u015faret\u00e7i i\u015faret ediyor s\u0131rayla ama o anki durum ne ise, o an onun fonksiyonu i\u015faret edildi\u011finden her seferinde ilgili durumun fonksiyonu \u00e7a\u011f\u0131r\u0131lm\u0131\u015f oluyor. Bu da ger\u00e7ek hayat\u0131n modellenmesi konusunda bizlere b\u00fcy\u00fck avantajlar sunuyor.<\/p>\n<p>Fonksiyon i\u015faret\u00e7ilerinin kullan\u0131m alanlar\u0131 elbette ki bununla s\u0131n\u0131rl\u0131 de\u011fil. E\u011fer bir SDK geli\u015ftiriyorsan\u0131z, muhtemelen Callback s\u00f6zc\u00fc\u011f\u00fc ile yat\u0131p, Callback s\u00f6zc\u00fc\u011f\u00fc ile kalkacaks\u0131n\u0131z. Bu callback mevzusunda da fonksiyon i\u015faret\u00e7ileri kullan\u0131l\u0131yor. \u015eimdi diyelim ki SDK geli\u015ftiriyorsunuz ve SDK&#8217;da \u00f6zel bir olay oldu\u011funda, kullan\u0131c\u0131n\u0131n size s\u00f6yledi\u011fi bir fonksiyonun \u00e7a\u011f\u0131r\u0131lmas\u0131n\u0131 istiyorsunuz. Yani \u00e7a\u011f\u0131r\u0131lacak fonksiyonu asl\u0131nda bilmiyorsunuz bile. Sadece o olay ger\u00e7ekle\u015ftirildi\u011finde, sisteme kaydedilmi\u015f bir callback var ise o \u00e7a\u011f\u0131r\u0131ls\u0131n istiyorsunuz. Bu i\u015fi nas\u0131l yazar\u0131z?<\/p>\n<pre class=\"lang:c decode:true\" title=\"mysdkfile.h\">#ifndef H_MYSDKFILE\r\n#define H_MYSDKFILE\r\n\r\n#include &lt;stdint.h&gt;\r\n\r\ntypedef void (*fpEventCallback)(void);\r\n\r\n\r\nvoid SDK_RegisterOverflowCallback(fpEventCallback OverflowCallback);\r\n\r\n#endif<\/pre>\n<pre class=\"lang:c decode:true\" title=\"mysdkfile.c\">#include \"mysdkfile.h\"\r\n\r\n#define SDK_EVENT_INFO_LIMIT (0x02EA)\r\n\r\nfpEventCallback SdkOvfCallback = NULL;\r\n\r\nvoid SDK_RegisterOverflowCallback(fpEventCallback OverflowCallback)\r\n{\r\n  if(NULL != OverflowCallback)\r\n  {\r\n    SdkOvfCallback = OverflowCallback;\r\n  }\r\n}\r\n\r\nvoid MyEvent(uint32_t eventInfo)\r\n{\r\n if(eventInfo &gt; SDK_EVENT_INFO_LIMIT &amp;&amp; (NULL != SdkOvfCallback))\r\n {\r\n   SdkOvfCallback(); \/\/ call the callback for overflow if it is registered\r\n }\r\n \/\/..\r\n\r\n}<\/pre>\n<p>\u015eimdi yukar\u0131da, SDK&#8217;y\u0131 yazanlar olarak biz \u00e7i\u00e7ek gibi event callback register mekanizmas\u0131n\u0131 verdik. Art\u0131k MyEvent olay\u0131 geldi\u011finde, e\u011fer olay bilgisi, s\u0131n\u0131r de\u011ferden b\u00fcy\u00fckse, kullan\u0131c\u0131n\u0131n verdi\u011fi herhangi bir fonksiyon \u00e7a\u011f\u0131r\u0131lacak. Bu fonksiyon herhangi bir i\u015f yapabilir, kullan\u0131c\u0131 ne isterse! Ama i\u00e7inde while(1); gibi terbiyesizliklerin olmamas\u0131 laz\u0131m! \u015eimdi SDK&#8217;y\u0131 kullanmak isteyen, usturuplu, terbiyeli bir yaz\u0131l\u0131mc\u0131 kendi fonksiyonunu nas\u0131l bizim SDK&#8217;ya kaydeder onu yazal\u0131m.<\/p>\n<pre class=\"lang:c decode:true\" title=\"myapp.c\">#include &lt;stdint.h&gt;\r\n#include \"mysdkfile.h\"\r\n\r\nvoid OverflowHandler(void)\r\n{\r\n   printf(\"There is an overflow! Mom, help me!!!rn\");\r\n   \r\n   OverflowFixerFunc();\r\n}\r\n\r\nint32_t main()\r\n{\r\n  InitializeSystem();\r\n\r\n  SDK_RegisterOverflowCallback(OverflowHandler);\r\n\r\n  for(;;)\r\n  {\r\n    DoWhatIsNeeded();\r\n  }\r\n}<\/pre>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi, bir fonksiyona parametre olarak ba\u015fka bir fonksiyonu verdik. \ud83d\ude42 Bu ibretlik olay\u0131 fonksiyon i\u015faret\u00e7ilerinin varl\u0131\u011f\u0131na bor\u00e7luyuz. Buradan indirilecek ibreti beyinlerimize indirdi\u011fimizi d\u00fc\u015f\u00fcn\u00fcyorum. \u00d6yleyse bir sonraki konuya ge\u00e7ebiliriz.<\/p>\n<p><strong>Genel \u0130\u015faret\u00e7i (Void Pointer, void*)<\/strong><\/p>\n<p>Hi\u00e7 uzatmadan konuya girece\u011fim. C dilinde, bir nevi joker olarak kullanabilece\u011fimiz, her yere yedirebilece\u011fimiz, her \u015feye cast edebilece\u011fimiz bir veri tipi bulunuyor. Bu veri tipi, \u00e7ok a\u00e7\u0131k s\u00f6yl\u00fcyorum void*&#8217;d\u0131r. Genel i\u015faret\u00e7i olarak tarif edebilece\u011fimiz bu i\u015faret\u00e7i tipi ile, her \u015feyi i\u015faret edebilirsiniz. Daha do\u011frusu, herhangi bir \u015feyi i\u015faret edebilirsiniz. Bu da bize jenerik kodlama yapma \u015fans\u0131 sa\u011fl\u0131yor.<\/p>\n<p>Diyelim iki veriyi toplayan bir fonksiyon yazacak olal\u0131m. Her bir veri tipi i\u00e7in ayr\u0131 ayr\u0131 topla fonksiyonu yazmadan nas\u0131l yapar\u0131z bu i\u015fi? T\u00fcm veri tipleri i\u00e7in olmasa da, 32 bite kadar olan standart veri tipleri i\u00e7in \u015f\u00f6yle yapar\u0131z:<\/p>\n<pre class=\"lang:c decode:true\">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\n\/*Maximum 32 bit numbers summation*\/\r\nuint32_t Summation(void* pParam1, void* pParam2 )\r\n{\r\n\tuint32_t retVal;\r\n\r\n   if(NULL != pParam1 &amp;&amp; NULL != pParam2)\r\n   {\r\n     retVal = ((*(uint32_t*)pParam1) + (*(uint32_t*)pParam2));\r\n   }\r\n   return retVal;\r\n}\r\n\r\nint32_t main()\r\n{\r\nint32_t i32Num1 = 29;\r\nint32_t i32Num2 = 11;\r\n\r\nint8_t i8Num1= 5;\r\nint8_t i8Num2= -2;\r\nprintf(\"Summation of int32_t numbers: %d\\r\\n\", (int32_t)Summation(&amp;i32Num1,&amp;i32Num2));\r\nprintf(\"Summation of int8_t numbers: %d\\r\\n\", (int8_t)Summation(&amp;i8Num1,&amp;i8Num2));\r\nreturn 0;\r\n}\r\n<\/pre>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi b\u00fcy\u00fck oranda jenerik bir fonksiyon yazm\u0131\u015f olduk. \u00a0Ayr\u0131ca void i\u015faret\u00e7isini di\u011fer tipteki i\u015faret\u00e7ilere cast etti\u011fimize dikkatinizi \u00e7ekerim. Bu mereti, her tipteki i\u015faret\u00e7iye cast etmek (aktarmak) m\u00fcmk\u00fcn.<\/p>\n<div class=\"su-box su-box-style-soft\" id=\"\" style=\"border-color:#2c85c7;border-radius:3px;\"><div class=\"su-box-title\" style=\"background-color:#5fb8fa;color:#FFFFFF;border-top-left-radius:1px;border-top-right-radius:1px\">Dikkat<\/div><div class=\"su-box-content su-u-clearfix su-u-trim\" style=\"border-bottom-left-radius:1px;border-bottom-right-radius:1px\">Yukar\u0131daki fonksiyon float veri tipi i\u00e7in do\u011fru \u00e7al\u0131\u015fmayacakt\u0131r. Float veri tipleri, derleyici taraf\u0131ndan IEEE754 format\u0131na uygun olarak -\u00f6zel y\u00f6ntemlerle- sakland\u0131\u011f\u0131ndan ve topland\u0131\u011f\u0131ndan, uint32 format\u0131 \u00fczerinden iki float say\u0131n\u0131n toplanmas\u0131 do\u011fru sonucu vermez. Yukar\u0131daki kodu, profesyonel uygulamalarda kullanmay\u0131n\u0131z.<\/div><\/div>\n<p>Son olarak k\u0131sa bir hat\u0131rlatma yapay\u0131m. Bir sistemin ka\u00e7 bitlik oldu\u011funu \u00f6\u011frenmek i\u00e7in:<\/p>\n<pre class=\"lang:c decode:true\">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\nint32_t main()\r\n{\r\n\r\nprintf(\"Bu platform %d bitliktirrn\", 8*sizeof(void*));\r\ngetchar();\r\n\r\nreturn 0;\r\n}<\/pre>\n<p>Bence void* b\u00fcy\u00fck oranda anla\u015f\u0131ld\u0131. \u015eimdi yine her zamanki sevimli hareketlerden birini yapaca\u011f\u0131z. Bilgilerimizi harmanlayaca\u011f\u0131z. Fonksiyon i\u015faret\u00e7ileri ile genel i\u015faret\u00e7ileri birle\u015ftirdi\u011fimizde ne kadar g\u00fc\u00e7l\u00fc bir \u015fey elde etti\u011fimizi d\u00fc\u015f\u00fcnelim.<\/p>\n<pre class=\"lang:default decode:true\">typedef void (*DataSendOverSerial)(void* pData, in32_t lenInBytes);<\/pre>\n<p>Yukar\u0131daki fonksiyon i\u015faret\u00e7isi tipi, giri\u015f parametresi olarak genel i\u015faret\u00e7iyi al\u0131yor. Yukar\u0131daki fonksiyon tipindeki bir fonksiyon, tip ayr\u0131m\u0131 yapmaks\u0131z\u0131n her t\u00fcrl\u00fc veriyi seri porttan g\u00f6nderebilir. Float olsun, int olsun, char olsun, int32_t olsun, hatta ve hatta bir fonksiyonu bile seri port \u00fczerinden g\u00f6nderebilirsiniz \ud83d\ude42 Ve ayn\u0131 zamanda size polimorfik bir yap\u0131 sunar. K\u0131zarm\u0131\u015f ekmek \u00fcst\u00fcnde bal kaymak gibi&#8230; Mis.. Afiyet olsun \ud83d\ude42 \u00d6yleyse devam!<\/p>\n<p><strong>K\u0131saltma \u0130\u00e7in \u0130\u015faret\u00e7iler<\/strong><\/p>\n<p>C dilinde, kompleks veri yap\u0131lar\u0131 diye bir mevzu var. \u0130lk ba\u015fta \u015faka gibi geliyor bu ifade ama baz\u0131 veri yap\u0131lar\u0131 hakikaten kompleks olabiliyor \ud83d\ude42 Bir sturct i\u00e7inde ba\u015fka bir struct, onun i\u00e7inde afedersiniz ba\u015fka bir struct, onun i\u00e7inde de bir i\u015faret\u00e7i d\u00fc\u015f\u00fcnelim. Bu durumda en alt seviyedeki de\u011fikene ula\u015fmak hakikaten baya\u011f\u0131 zaman alacakt\u0131r. \u00d6zellikle tembel yaz\u0131l\u0131mc\u0131lar\u0131, klavyede bu kadar tu\u015fa basmaktan nefret ederler. Bu gibi durumlarda da k\u0131saltma ama\u00e7l\u0131 olarak i\u015faret\u00e7ilerden faydalanabiliriz. Misal:<\/p>\n<pre class=\"lang:c decode:true \">typedef struct\r\n{\r\n  int8_t test1;\r\n  int8_t mest1;\r\n  int8_t jest1;\r\n  int8_t kest1;\r\n  int8_t lest1;\r\n}s_Struct3;\r\n\r\n\/\/myStruct3'\u00fcn tipi s_Struct3* olsun.\r\nagaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3-&gt;test1 = 1;\r\nagaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3-&gt;mest1 = 2;\r\nagaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3-&gt;jest1 = 3;\r\nagaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3-&gt;kest1 = 4;\r\nagaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3-&gt;lest1 = 5;\r\n\r\n\/\/yazmak yerine;\r\ns_Struct3* kucukStruct3;\r\nkucukStruct3 = agaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3;\r\nkucukStruct3-&gt;test1 = 1;\r\nkucukStruct3-&gt;mest1 = 2;\r\nkucukStruct3-&gt;jest1 = 3;\r\nkucukStruct3-&gt;kest1 = 4;\r\nkucukStruct3-&gt;lest1 = 5;\r\n\/\/yazmak suphesiz daha kisa oluyor<\/pre>\n<p>\u0130lk bak\u0131\u015fta komik bir kullan\u0131m alan\u0131 gibi g\u00f6z\u00fckse de, i\u015fin i\u00e7ine girdi\u011fimizde bu tip kullan\u0131mlar\u0131n yads\u0131namaz miktarda oldu\u011funu g\u00f6r\u00fcyoruz. Belki de tembelli\u011fin b\u00f6ylesi cand\u0131r canand\u0131r \ud83d\ude42 Tabi burada bir pointer&#8217;\u0131 ekstradan kullanarak bellekten biraz \u00e7ald\u0131k. De\u011fer mi de\u011fmez mi o karar\u0131 size b\u0131rak\u0131yorum.<\/p>\n<p><strong>Diziler ve \u0130\u015faret\u00e7iler<\/strong><\/p>\n<p>Diziler ve i\u015faret\u00e7iler birbirlerine \u00e7ok \u00e7ok yak\u0131n iki kavramd\u0131r. Nihayetinde her bir dizi, asl\u0131nda bir i\u015faret\u00e7idir. Ancak bu \u00f6zel i\u015faret\u00e7iler tan\u0131mlan\u0131rken, i\u015faret edecekleri bellek alanlar\u0131 \u00f6nceden ayr\u0131l\u0131r.<\/p>\n<p>Diziler de t\u0131pk\u0131 di\u011fer de\u011fi\u015fkenler gibi ilk de\u011fer atamas\u0131 mevzular\u0131na tabidir. \u0130lk de\u011fer atamas\u0131 yap\u0131lmam\u0131\u015f bir dizi tan\u0131m\u0131 a\u015fa\u011f\u0131daki gibidir:<\/p>\n<pre class=\"lang:c decode:true \">uint8_t u8TestArray[10];<\/pre>\n<p>Burada yaln\u0131zca dizinin 10 elemanl\u0131 olaca\u011f\u0131 bilgisi verilmi\u015f. yani u8TestArray de\u011fi\u015fkeninin i\u015faret etti\u011fi bellek adresinden ba\u015flamak \u00fczere 10 byte bu dizinin elemanlar\u0131 olarak s\u0131ralanacak.<\/p>\n<p>\u015eimdi ilk de\u011fer atamas\u0131 yap\u0131lm\u0131\u015f ancak boyut verilmemi\u015f bir diziye bakal\u0131m.<\/p>\n<pre class=\"lang:c decode:true\">int8_t testArray[] = \"Hello!\";<\/pre>\n<p>Burada test array asl\u0131nda bildi\u011fimiz i\u015faret\u00e7idir. G\u00f6rd\u00fc\u011f\u00fcn\u00fcz \u00fczere kendisine &#8220;Hello!&#8221; \u015feklindeki karakter dizisini yani \u00a0string&#8217;i atam\u0131\u015f olduk. C dilinde string, ayr\u0131 bir tip de\u011fildir ancak karakterlerden olu\u015fan bir dizidir. Nitekim yukar\u0131dakinin bir benzeri \u015f\u00f6yledir:<\/p>\n<pre class=\"lang:default decode:true\">int8_t *testPtr = (int8_t*) \"Hello!\";<\/pre>\n<p>testArray dedi\u011fimiz \u015fey asl\u0131nda \u015fu a\u015fa\u011f\u0131daki ile ayn\u0131d\u0131r:<\/p>\n<pre class=\"lang:default decode:true \">&amp;testAray[0];<\/pre>\n<p>\u00c7\u00fcnk\u00fc dizinin ismi yani de\u011fi\u015fken ad\u0131 (testArray), asl\u0131nda dizinin ilk eleman\u0131n\u0131n adresini ta\u015f\u0131r (&amp;testArray[0]).<\/p>\n<p>\u0130\u015fte bunun fark\u0131nda olmakta ve bunu unutmamakta faydalar var.<\/p>\n<p>Yukar\u0131daki \u00f6rnekte verdi\u011fimiz Hello! yaz\u0131s\u0131n\u0131 karakter karakter yazd\u0131rmak istesek dizinin her bir eleman\u0131n\u0131 yazd\u0131rabilece\u011fimiz gibi, pointer aritmeti\u011fi \u00a0ile de ayn\u0131 i\u015fi yapabiliriz.<\/p>\n<pre class=\"lang:c decode:true \">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\n\r\nint32_t main()\r\n{\r\nint8_t* testPtr = (int8_t*)\"Hello!\";\r\n\r\nwhile(*testPtr)\r\n{\r\n    printf(\"%c\",*testPtr++);\r\n}\r\ngetchar();\r\n  return 0;\r\n}<\/pre>\n<p><strong>Struct ve \u0130\u015faret\u00e7iler<\/strong><\/p>\n<p>Yap\u0131lar ba\u015fl\u0131kl\u0131 yaz\u0131mda esasen bu konuya de\u011finmi\u015ftim ancak ufaktan tekrar etmekte fayda var diye d\u00fc\u015f\u00fcn\u00fcyorum. Struct genelde kocaman bir yap\u0131y\u0131 modelledi\u011finden bellekte kaplad\u0131\u011f\u0131 yer ciddiye al\u0131nmal\u0131d\u0131r. Hal-i haz\u0131rda k\u00fc\u00e7\u00fcc\u00fck olup ciddiye almad\u0131\u011f\u0131n\u0131z bir struct, yaz\u0131l\u0131m\u0131n bir sonraki versiyonunda b\u00fcy\u00fcyebilir ve size ciddiye almak zorunda kalaca\u011f\u0131n\u0131z baz\u0131 problemler yaratabilir. O sebeple sayg\u0131y\u0131 ba\u015ftan g\u00f6stermekte faydalar var.<\/p>\n<p>Bir struct tan\u0131mland\u0131ktan ve onunla ilgili bilgi belle\u011fe yaz\u0131ld\u0131ktan sonra, o veriyi kullanmak i\u00e7in ba\u015fka bir sturct yaratmak \u00e7o\u011fu durumda anlams\u0131z ve mant\u0131ks\u0131zd\u0131r. Onun yerine struct i\u015faret\u00e7isi tan\u0131mlanarak, ilgili struct&#8217;\u0131 i\u015faret edecek \u015fekilde de\u011fer atamas\u0131 yap\u0131lmas\u0131nda say\u0131s\u0131z faideler ve feyizler vard\u0131r.<\/p>\n<p><strong>Union ve \u0130\u015faret\u00e7iler<\/strong><\/p>\n<p>Union bildi\u011finiz \u00fczere; her eleman\u0131 belle\u011fin ayn\u0131 adresini g\u00f6steren \u00f6zel bir yap\u0131. Kendisinin feyizli \u00f6zelliklerini sizlerle payla\u015fm\u0131\u015ft\u0131k. Ancak tan\u0131m\u0131ndan da anla\u015f\u0131labilece\u011fi \u00fczere kendisi asl\u0131nda bir \u00e7e\u015fit \u00f6zel i\u015faret\u00e7idir. Dolay\u0131s\u0131yla union kullanarak yapabilece\u011fimiz bir \u00e7ok i\u015fi, \u00e7ok daha \u00e7irkin \u015fekilde do\u011frudan i\u015faret\u00e7ilerle de yapabiliriz. Misal:<\/p>\n<pre class=\"lang:c decode:true \">uint32_t nRead;\r\n   uint32_t index;\r\n   typedef union {\r\n       uint32_t u32Data;\r\n       int16_t  as16Data[2];\r\n       int8_t   as8Data[4];\r\n   }tu_DataGroup32;\r\n \r\n   tu_DataGroup32 UData;\r\n   \/\/ ( Code to read in nRead, from the user or a file, has been omitted in this example )\r\n    UData.u32Data = nRead;\r\n    for(  index= 0; index &lt; sizeof(uint32_t); index++ )\r\n    {\r\n        printf( \"Byte number %d of %ud is %udn\", index, nRead, UData.as8Data[index] );\r\n    }<\/pre>\n<p>yerine benzer i\u015fi yapan \u015f\u00f6yle bir kod da yazabiliriz.<\/p>\n<pre class=\"lang:c decode:true\">uint32_t nRead;\r\n   uint32_t index;\r\n\r\n    for(  index= 0; index &lt; sizeof(uint32_t); index++ )\r\n    {\r\n        printf( \"Byte number %d of %ud is %udn\", index, nRead, (*(int8_t*)((&amp;nRead) + index)) );\r\n    }<\/pre>\n<p>Ama dedi\u011fim gibi \u00e7irkin olur kem olur. Parantez manya\u011f\u0131 olmak zorunda kal\u0131r\u0131z ve kodumuz da anla\u015f\u0131lmaz.<\/p>\n<p>Ancak yine de olay\u0131n alt\u0131nda yatan felsefeyi bilmekte faideler var.<\/p>\n<p><strong>NULL \u0130\u015faret\u00e7isi<\/strong><\/p>\n<p>Bu NULL denen nane \u00e7ok me\u015fhurdur, her yerde de kullan\u0131l\u0131r. NULL i\u015faret\u00e7isi esasen belle\u011fin 0 numaral\u0131 adresini g\u00f6steren bir i\u015faret\u00e7idir. Kendisinin tipi void*&#8217;d\u0131r.<\/p>\n<p>K\u00fct\u00fcphanelerdeki (stddef.h) tan\u0131m\u0131na bakt\u0131\u011f\u0131m\u0131z zaman \u015funu g\u00f6r\u00fcr\u00fcr\u00fcz:<\/p>\n<pre class=\"lang:c decode:true \">#define NULL ((void*) 0)<\/pre>\n<p>NULL dedi\u011fimiz nane i\u015fte budur. Belle\u011fin 0 nolu b\u00f6lgesini g\u00f6steren bir i\u015faret\u00e7i. Peki neden bir i\u015faret\u00e7inin &#8220;bo\u015f&#8221; olup olmad\u0131\u011f\u0131n\u0131 kontrol etmek i\u00e7in bunu kullan\u0131r\u0131z? \u00c7\u00fcnk\u00fc bir i\u015faret\u00e7i ilk de\u011fer atamas\u0131 yap\u0131lana kadar s\u0131f\u0131r nolu bellek adresini g\u00f6sterir. Dolay\u0131s\u0131yla bu ona ilk de\u011fer atamas\u0131 yap\u0131lmad\u0131\u011f\u0131n\u0131 anlaman\u0131n g\u00fczel bir yoludur.<\/p>\n<p><strong>Fonksiyonlara Arg\u00fcman\u00a0Olarak\u00a0\u0130\u015faret\u00e7iler<\/strong><\/p>\n<p>Fonksiyonun pahal\u0131 bir de\u011fi\u015fken oldu\u011funu her f\u0131rsatta s\u00f6yl\u00fcyorum, s\u00f6ylemeye de devam edece\u011fim. \u015eimdi bu pahal\u0131l\u0131kta \u00f6nemli bir gider kalemi de fonksiyonlar\u0131n arg\u00fcmanlar\u0131d\u0131r. Bir fonksiyonun arg\u00fcmanlar\u0131 belle\u011fin \u00f6zel bir b\u00f6lgesine kopyalan\u0131r. S\u00f6z\u00fc uzatmadan mevzuya dalaca\u011f\u0131m. E\u011fer kopyalanan \u015fey devasa bir struct ise vay halinize. Ne demi\u015ftik? Struct kopyalamak \u00e7o\u011fu durumda mant\u0131ks\u0131zd\u0131r. Demek ki fonksiyona arg\u00fcman olarak struct yerine struct i\u015faret\u00e7isini vermekte fayda var. Bu ayn\u0131 zamanda fonksiyonun kullanaca\u011f\u0131 belle\u011fin, fonksiyonu \u00e7a\u011f\u0131racak ki\u015fi taraf\u0131ndan ayr\u0131lmas\u0131na (allocate etmek) izin verdi\u011finden, (caller allocation prensibi) fevkalade lezzetli bir olayd\u0131r.<\/p>\n<p>Bu mevzu hakk\u0131nda detayl\u0131 bilgiyi ve \u00f6rnek kodlar\u0131 <a href=\"http:\/\/ozenozkaya.com\/blog\/?p=286\" target=\"_blank\" rel=\"noopener\">BURADAN<\/a>, &#8220;<strong>Struct\u2019lar\u0131n\u00a0Pointer(\u0130\u015faret\u00e7i) ile \u0130mtihan\u0131&#8221;\u00a0<\/strong>ba\u015fl\u0131kl\u0131 b\u00f6l\u00fcmden bulabilirsiniz.<\/p>\n<p>Fonksiyonlara arg\u00fcman olarak i\u015faret\u00e7i verilmesinin bir di\u011fer \u00f6nemli kullan\u0131m alan\u0131 da, o fonksiyonun arg\u00fcman\u0131n\u0131 fonksiyon i\u00e7inde de\u011fi\u015ftirmesine olanak vermektir. Bu \u00f6zellik yads\u0131namaz derecede \u00f6nemlidir. Her fonksiyon tek i\u015f yapmal\u0131d\u0131r demi\u015ftik ama baz\u0131 durumlarda bir fonksiyonun birden fazla de\u011fer d\u00f6nd\u00fcrmesi gerekebilir. \u00d6yleyse o de\u011ferlerin arg\u00fcmanlarda i\u015faret\u00e7i olarak al\u0131nmas\u0131 yeterli olacakt\u0131r \u00e7\u00fcnk\u00fc bir kez de\u011fi\u015fkenin adresi bilindi mi, onun i\u00e7indeki veriyi man\u00fcple etmek problem olmayacakt\u0131r \ud83d\ude42<\/p>\n<p>Hemen k\u0131sa bir \u00f6rnek vereyim:<\/p>\n<pre class=\"lang:default decode:true\">#include &lt;stdio.h&gt;\r\n#include &lt;stdint.h&gt;\r\n\r\nvoid Function1(int8_t a);\r\nvoid Function2(int8_t* a);\r\n\r\nint32_t main()\r\n{\r\nint8_t a = 55;\r\nprintf(\"a'nin degeri %drn\",a);\r\n Function1(a);\r\nprintf(\"a'nin degeri %drn\",a);\r\nFunction2(&amp;a);\r\nprintf(\"a'nin degeri %drn\",a);\r\n\r\ngetchar();\r\nreturn 0;\r\n}\r\n\r\n\r\nvoid Function1(int8_t a)\r\n{\r\n  a++;\r\n  printf(\"%s icinde a'nin degeri %drn\",__FUNCTION__,a);\r\n}\r\nvoid Function2(int8_t* a)\r\n{\r\n  (*a)++;\r\n  printf(\"%s icinde a'nin degeri %drn\",__FUNCTION__,*a);\r\n}<\/pre>\n<p>Bu kod \u00e7al\u0131\u015ft\u0131r\u0131ld\u0131\u011f\u0131nda \u00e7\u0131kt\u0131s\u0131 \u015f\u00f6yle olur:<\/p>\n<div class=\"su-box su-box-style-soft\" id=\"\" style=\"border-color:#00c500;border-radius:3px;\"><div class=\"su-box-title\" style=\"background-color:#2cf828;color:#FFFFFF;border-top-left-radius:1px;border-top-right-radius:1px\">Konsol \u00c7\u0131kt\u0131s\u0131<\/div><div class=\"su-box-content su-u-clearfix su-u-trim\" style=\"border-bottom-left-radius:1px;border-bottom-right-radius:1px\">a&#8217;nin degeri 55<br \/>\nFunction1 icinde a&#8217;nin degeri 56<br \/>\na&#8217;nin degeri 55<br \/>\nFunction2 icinde a&#8217;nin degeri 56<br \/>\na&#8217;nin degeri 56<\/p>\n<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br \/>\nProcess exited with return value 0<br \/>\nPress any key to continue . . .<br \/>\n<\/div><\/div>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi Fonksiyon1, a de\u011fi\u015fkenini fonksiyonun d\u0131\u015f\u0131nda etkili olacak \u015fekilde de\u011fi\u015ftirememi\u015f, ancak Fonksiyon2 de\u011fi\u015ftirebilmi\u015ftir. Bunun sebebi asl\u0131nda basittir, Fonksiyon1 a de\u011fi\u015fkeninin kendisini de\u011fil, adi bir kopyas\u0131n\u0131 de\u011fi\u015ftirmi\u015ftir. Nitekim a&#8217;lar\u0131n adresleri yazd\u0131r\u0131lsa farkl\u0131 \u00e7\u0131kacakt\u0131r. Bu merete Japonlar bunshin diyor \ud83d\ude00 Bilenler bilir.<\/p>\n<p><strong>Komut Sat\u0131r\u0131 Giri\u015fi<\/strong><\/p>\n<p>Son olarak, komut sat\u0131r\u0131 arg\u00fcmanlar\u0131ndan bahsedece\u011fim. Bu, g\u00f6m\u00fcl\u00fc sistemlerde \u00e7ok da \u00f6nemli de\u011fil ancak bilmekte faydalar var.<\/p>\n<pre class=\"lang:c decode:true \">int main( int argc,char * argv[ ] );\r\nint main( int argc, char **argv );<\/pre>\n<p>Yukar\u0131dakiler hemen hemen ayn\u0131 mevzular. Siz yazd\u0131\u011f\u0131n\u0131z kodu derleyip konsoldan \u00e7a\u011f\u0131rd\u0131\u011f\u0131n\u0131zda ona parametre verebilirsiniz. Bunun ad\u0131 komut sat\u0131r\u0131 arg\u00fcmanlar\u0131d\u0131r ve program \u00e7a\u011f\u0131r\u0131l\u0131rken bu bilgi programa verilebilir. G\u00f6m\u00fcl\u00fc sistemlerde kodu komut sat\u0131r\u0131ndan \u00e7a\u011f\u0131rmad\u0131\u011f\u0131n\u0131zdan bu olay bu ama\u00e7la kullan\u0131lmaz ama ba\u015fka ama\u00e7larla kullan\u0131labilir \ud83d\ude42 \u00d6nemli olan mevzu \u015fudur; verdi\u011finiz arg\u00fcmanlar aras\u0131ndaki bo\u015fluk bulunan kelimelerdir. Bu kelimelerin say\u0131s\u0131 argc&#8217;ye, kendileri de argv&#8217;ye i\u015fletim sistemi taraf\u0131ndan aktar\u0131l\u0131r.<\/p>\n<p>Hemen \u00e7ok s\u0131k verilen \u015fu kodu biz de \u00f6rnek olarak verelim:<\/p>\n<pre class=\"lang:c decode:true \">#include&lt;stdio.h&gt;\r\n\r\nint main(int argc,char **argv)\r\n{\r\nint i;\r\nfor(i=0;i&lt;argc;i++)\r\n{\r\nprintf(\u201c%sn\u201d,argv[i]);\r\n}\r\nreturn 0;\r\n}<\/pre>\n<p>Bu kodu selam.c olarak kaydedip derledi\u011fimizi, ve \u00e7\u0131kt\u0131\u00a0olan program\u0131n ad\u0131n\u0131n\u00a0da selam oldu\u011funu d\u00fc\u015f\u00fcn\u00fcyorum. Komut sat\u0131r\u0131ndan program\u0131 \u015f\u00f6yle \u00e7a\u011f\u0131ral\u0131m &#8220;selam kardes kafan cok guzelmis nerden aldin?&#8221;<\/p>\n<p>Bu durumda komut sat\u0131r\u0131na girilen arg\u00fcman say\u0131s\u0131 argc = 7 olacakt\u0131r. argv[0]&#8217;\u0131n g\u00f6sterdi\u011fi yerde program\u0131n ad\u0131 yani selam yazacakken argv[1]&#8217;in g\u00f6sterdi\u011fi yerde kardes yazacakt\u0131r. Dolay\u0131s\u0131yla bu kodun \u00e7\u0131kt\u0131s\u0131 \u015f\u00f6yle olur:<\/p>\n<div class=\"su-box su-box-style-soft\" id=\"\" style=\"border-color:#00c500;border-radius:3px;\"><div class=\"su-box-title\" style=\"background-color:#2cf828;color:#FFFFFF;border-top-left-radius:1px;border-top-right-radius:1px\">Konsol \u00c7\u0131kt\u0131s\u0131<\/div><div class=\"su-box-content su-u-clearfix su-u-trim\" style=\"border-bottom-left-radius:1px;border-bottom-right-radius:1px\">selam<br \/>\nkardes<br \/>\nkafan<br \/>\ncok<br \/>\nguzelmis<br \/>\nnerden<br \/>\naldin?<br \/>\n<\/div><\/div>\n<p><strong>S\u0131k Yap\u0131lan Hatalar<\/strong><\/p>\n<p>Arkada\u015flar i\u015faret\u00e7ilerin bili\u00e7siz kullan\u0131mas\u0131 \u00e7ok say\u0131da hataya yol a\u00e7abilir ve bunlar ger\u00e7ekten zorlu hatalar olacakt\u0131r. Ancak sizler, i\u015faret\u00e7ileri buradaki bilgilerle birlikte kulland\u0131\u011f\u0131n\u0131zda bu sorunlar\u0131 zaten ya\u015famayacaks\u0131n\u0131z \ud83d\ude42<\/p>\n<p>*Misal a\u015fa\u011f\u0131daki gibi bir kod yazmayaca\u011f\u0131n\u0131z\u0131 umuyorum:<\/p>\n<pre class=\"lang:c decode:true\">int32_t * ptr , m = 100 ;\r\n      ptr = m ;       \/\/eyvah! dogrusu ptr = &amp;m olacak!<\/pre>\n<p>*Bir di\u011fer hata da ilk de\u011fer atanmam\u0131\u015f bir i\u015faret\u00e7inin g\u00f6stermedi\u011fi belle\u011fin i\u00e7ine bir \u015feyler yazmaya \u00e7al\u0131\u015fmakt\u0131r. Kemdir, puan g\u00f6t\u00fcr\u00fcr, yapmay\u0131n\u0131z. Misal:<\/p>\n<pre class=\"lang:c decode:true\">int32_t * ptr , m = 100 ;\r\n*ptr = m ;            \/\/ eyvah! daha ptr'nin nereyi g\u00f6sterdi\u011fi belli degil<\/pre>\n<p>Daha ptr&#8217;nin nereyi g\u00f6sterdi\u011fini ayarlamadan, bu belle\u011fin i\u00e7ine m&#8217;nin de\u011ferini yazmaya \u00e7al\u0131\u015f\u0131yoruz. \u00d6nce bu ptr bir yeri g\u00f6stermeli. Misal:<\/p>\n<pre class=\"lang:default decode:true\">int32_t * ptr;\r\nint32_t m = 100 ,n = 20;\r\nptr = &amp;n;\r\n*ptr = m ;<\/pre>\n<p>*Di\u011fer bir hata da, bir i\u015faret\u00e7inin, ilk de\u011fer atanmam\u0131\u015f bir de\u011fi\u015fkeni i\u015faret etmeye \u00e7al\u0131\u015fmas\u0131d\u0131r. Bu \u015f\u0131k bir kullan\u0131m de\u011fildir. \u00d6nce i\u015faret edilecek de\u011fi\u015fkene ilk de\u011fer atamakta faydalar vard\u0131r.<\/p>\n<pre class=\"lang:c decode:true\">int32_t *ptr,\r\nint32_t m;\r\nptr = &amp;m;<\/pre>\n<p>*\u0130ki i\u015faret\u00e7iyi kar\u015f\u0131la\u015ft\u0131rmak da iyi bir fikir say\u0131lmaz. \u0130\u015faret\u00e7iler, bellekteki rastgele alanlar\u0131 g\u00f6sterece\u011finden, i\u015faret\u00e7ileri do\u011frudan kar\u015f\u0131la\u015ft\u0131rmak anlams\u0131zd\u0131r. Anlaml\u0131 olabilecek \u015fey, bunlar\u0131n g\u00f6sterdi\u011fi de\u011ferleri kar\u015f\u0131la\u015ft\u0131rmakt\u0131r.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true \">char str1[10],str2[10];\r\nchar *ptr1 = str1;\r\nchar *ptr2 = str2;\r\n\r\nif(ptr1 &gt; ptr2)  .....   \/\/ Eyvah\r\n{\r\n....\r\n....\r\n}\r\n\r\n\r\nif(*ptr1 &gt; *ptr2)  .....   \/\/ Eyvallah\r\n{\r\n....\r\n....\r\n}<\/pre>\n<p>Daha bunu s\u0131ralamakla bitmez ama siz anlad\u0131n\u0131z mevzuyu.<\/p>\n<p>Yaz\u0131lar\u0131 be\u011fendiyseniz e\u011fer, \u00a0faydalanabilecek arkada\u015flar\u0131n\u0131zla da payla\u015fabilirseniz sevinirim.<\/p>\n<p>\u015eimdi devam&#8230;<\/p>\n<a href=\"http:\/\/ozenozkaya.com\/blog\/?p=294\" class=\"su-button su-button-style-3d\" style=\"color:#FFFFFF;background-color:#2D89EF;border-color:#246ec0;border-radius:5px\" target=\"_self\"><span style=\"color:#FFFFFF;padding:6px 16px;font-size:13px;line-height:20px;border-color:#6cadf4;border-radius:5px;text-shadow:none\"><i class=\"sui sui-arrow-circle-o-left\" style=\"font-size:13px;color:#FFFFFF\"><\/i> \u00d6nceki Sayfa<\/span><\/a> \u00a0<a href=\"http:\/\/ozenozkaya.com\/blog\/\" class=\"su-button su-button-style-3d\" style=\"color:#FFFFFF;background-color:#2D89EF;border-color:#246ec0;border-radius:5px\" target=\"_self\"><span style=\"color:#FFFFFF;padding:6px 16px;font-size:13px;line-height:20px;border-color:#6cadf4;border-radius:5px;text-shadow:none\"><i class=\"sui sui-arrow-circle-right\" style=\"font-size:13px;color:#FFFFFF\"><\/i> Sonraki Sayfa<\/span><\/a>\n","protected":false},"excerpt":{"rendered":"<p>\u0130\u015faret\u00e7iler (pointers) ba\u015fl\u0131kl\u0131 yaz\u0131mda konuyla ilgili g\u00fczel bir girizgah ve temel atma merasimi tertip\u00a0ettik. \u015eimdi, i\u015faret\u00e7ilerle ilgili daha ileri konulara de\u011finmenin tam s\u0131ras\u0131. \u0130\u015fin asl\u0131 i\u015faret\u00e7ilerin kullan\u0131m alanlar\u0131 \u00e7ok \u00e7ok geni\u015f. Tilkiler normalde yaln\u0131z dola\u015f\u0131r ama i\u015faret\u00e7iler de\u011fince akl\u0131mda bin bir tilki s\u00fcr\u00fc halinde dola\u015f\u0131yor. Hepsini burada yazmak \u00e7ok m\u00fcmk\u00fcn m\u00fc bilmiyorum ancak, elimden geldi\u011fince <a class=\"read-more\" href=\"http:\/\/ozenozkaya.com\/blog\/?p=305\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_tr_post_content":"\u0130\u015faret\u00e7iler (pointers) ba\u015fl\u0131kl\u0131 yaz\u0131mda konuyla ilgili g\u00fczel bir girizgah ve temel atma merasimi tertip\u00a0ettik. \u015eimdi, i\u015faret\u00e7ilerle ilgili daha ileri konulara de\u011finmenin tam s\u0131ras\u0131. \u0130\u015fin asl\u0131 i\u015faret\u00e7ilerin kullan\u0131m alanlar\u0131 \u00e7ok \u00e7ok geni\u015f. Tilkiler normalde yaln\u0131z dola\u015f\u0131r ama i\u015faret\u00e7iler de\u011fince akl\u0131mda bin bir tilki s\u00fcr\u00fc halinde dola\u015f\u0131yor. Hepsini burada yazmak \u00e7ok m\u00fcmk\u00fcn m\u00fc bilmiyorum ancak, elimden geldi\u011fince yazmaya \u00e7al\u0131\u015faca\u011f\u0131m.\r\n\r\nEfendim \u00f6zellikle belle\u011fi etkin kullanma noktas\u0131nda, i\u015faret\u00e7iler ziyadesiyle \u00f6nemli bir fakt\u00f6r oluyor.\u00a0Bu sebepledir ki g\u00f6m\u00fcl\u00fc programlama yapacak yi\u011fitlerin i\u015faret\u00e7ilerin suyunu s\u0131kmas\u0131 gerekmektedir. Mevzunun \u00f6z\u00fct\u00fc yine ayn\u0131 olsa da, her bir kullan\u0131m alan\u0131ndan al\u0131nacak say\u0131s\u0131z ibretler oldu\u011fundan, farkl\u0131ca \u00f6rnekler \u00fczerinden i\u015faret\u00e7ileri inceleyemeye \u00e7al\u0131\u015faca\u011f\u0131m. Yine de eksik kalan bir kullan\u0131m alan\u0131 oldu\u011funu d\u00fc\u015f\u00fcn\u00fcyorsan\u0131z, yorum olarak ekleyebilirsiniz.\r\n\r\nBu yaz\u0131y\u0131 okumay\u0131 bitirdi\u011finizde varaca\u011f\u0131m\u0131z noktada iki yol var.\r\n<ol>\r\n \t<li>Bu \u015feyler sizler i\u00e7in yeni \u015feyler ise, bunlar\u0131 sindirdi\u011finizde o \u00e7ok korkulan i\u015faret\u00e7iler konusunda harbici bir uzman olmu\u015f olacaks\u0131n\u0131z.<\/li>\r\n \t<li>Bu \u015feylerin tamam\u0131n\u0131 zaten biliyorsan\u0131z, \u00a0zaten bir uzmans\u0131n\u0131z. L\u00fctfen\u00a0siz de blog yaz\u0131n, haber edin biz de takip edelim yeni \u015feyler \u00f6\u011frenelim :)<\/li>\r\n<\/ol>\r\nNeyse \u015fimdi derin bir nefes al\u0131p ba\u015flayal\u0131m. Zira bu konular ciddi konular. Tek nefes yetmeyecek ama her nefesi derin almakta faydalar var.\r\n\r\n<strong>Mutlak Adres \u0130\u015faret\u00e7ileri (Pointers to Absolute Addresses)<\/strong>\r\n\r\n\u0130\u015faret\u00e7ilerin genel felsefesini bir \u00f6nceki yaz\u0131da konu\u015ftuk. Genelde bir tipteki bir i\u015faret\u00e7i, genelde ayn\u0131 tipteki bir de\u011fi\u015fkeni i\u015faret ediyordu. Peki ya bir i\u015faret\u00e7i, sabit bir adresi i\u015faret ederse?\r\n\r\nHmm. \u0130yi g\u00fczel, etsin de niye etsin? G\u00f6m\u00fcl\u00fc sistemlerde g\u00f6receksiniz ki, \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131z platformun (mikrokontrol\u00f6r, fpga, SoC, vs) sabit bir bellek haritas\u0131 var. Yani ROM,RAM, \u00e7evreseller filan hep sabit adreslerden ba\u015flar. Do\u011fal olarak, register'lar da sabit adreslere sahiptir.\r\n\r\n[su_box title=\"Register Ne Ki?\" style=\"noise\" box_color=\"#45ade5\"]\u0130lk defa duyanlar i\u00e7in register; g\u00f6m\u00fcl\u00fc sistemde donan\u0131m\u0131n izin verdi\u011fi baz\u0131 donan\u0131msal konfig\u00fcrasyonlar\u0131 saklamak i\u00e7in kullan\u0131lan bellek alan\u0131d\u0131r. \u00d6rne\u011fin bir pinin giri\u015f olarak m\u0131, \u00e7\u0131k\u0131\u015f olarak m\u0131 konfig\u00fcre edildi\u011fi bir regsiter'da tutulur. T\u00fcrk\u00e7e'ye \"k\u00fct\u00fck\" olarak \u00e7evrilmi\u015ftir ancak bu \u00e7eviri k\u00fct\u00fck gibi bir \u00e7eviri oldu\u011fundan, ben d\u00fczg\u00fcn bir \u00e7eviri \u00e7\u0131kana kadar register diyece\u011fim.\u00a0[\/su_box]\r\n\r\nRegister'lar sabit adreslere sahiptir dedik. \u00d6yleyse biz bunlara eri\u015firken yani buralar\u0131 i\u015faret ederken asl\u0131nda sabit adresleri i\u015faret edece\u011fiz. Bu vesile ile\u00a0mutlak adresleri i\u015faret eden i\u015faret\u00e7ilerin nerede kullan\u0131laca\u011f\u0131 hususunu apa\u00e7\u0131k bir \u015fekilde g\u00f6zler \u00f6n\u00fcne sermi\u015f olduk.\r\n\r\n\u00d6yleyse \u015fimdi bir \u00f6rnek \u00fczerinden gidelim. Diyelim ki bizim mikrokontrol\u00f6r\u00fcn \u00fc\u00e7 tane versiyonu var: A,B,C. Ve elimizdeki mikrokontrol\u00f6r\u00fcn 0xC0FFE nolu bellek adresinde bu k\u0131ymetli bilgi yaz\u0131yor. Bu bilgiyi nas\u0131l okuyaca\u011f\u0131z? Hemen yazal\u0131m!\r\n<pre class=\"lang:c decode:true\">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\n#define REG_DEVICE_TYPE_ID_CHAR (0xC0FFE)\r\n\r\nint32_t main()\r\n{\r\n  int8_t *pRegDevTypeIdChar = (int8_t*)REG_DEVICE_TYPE_ID_CHAR;\r\n  \r\n  printf(\"Device Type ID Char = %c\", *pRegDevTypeIdChar);\r\n\r\n  return 0;\r\n}<\/pre>\r\nNotasyon ve kod gayet temiz diye d\u00fc\u015f\u00fcn\u00fcyorum. Peki diyelim ayn\u0131 mikrokontrol\u00f6r\u00fcn 0xFACE adresinde bulunan register da mikrokontrol\u00f6r\u00fc ba\u015flatmak i\u00e7in olsun. Bizim mikrokontrol\u00f6r\u00fc ba\u015flatmak i\u00e7in ille de 0xFACE adresine 'S' yazmak gereksin. Onu nas\u0131l yapard\u0131k?\r\n<pre class=\"lang:c decode:true\">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\n#define REG_DEVICE_START_CMD (0xFACE)\r\n#define CMD_DEVICE_START ('S')\r\n#define CMD_DEVICE_PAUSE ('P')\r\n#define CMD_DEVICE_RESET ('R')\r\n\r\nint32_t main()\r\n{\r\n  int8_t *pRegDevStartCmd = (int8_t*)REG_DEVICE_START_CMD ;\r\n \r\n  \/\/Start device by writing relevant register to 'S'\r\n  *pRegDevStartCmd = CMD_DEVICE_START;\r\n  \r\n  \/\/...\r\n  \r\n  \/\/Pause Device by writing relevant register to 'P'\r\n  *pRegDevStartCmd = CMD_DEVICE_PAUSE ;\r\n\r\n  return 0\r\n}<\/pre>\r\n[su_box title=\"\u00d6NEML\u0130 NOT!\" style=\"noise\" box_color=\"#45ade5\"]NOT: Yukar\u0131daki kodu bilgisayar\u0131n\u0131za at\u0131p \u00e7al\u0131\u015ft\u0131rmay\u0131n diye return 0'dan sonraki virg\u00fcl\u00fc sildim ve sistemin \u00f6zellikle derleme hatas\u0131 vermesini istedim. Bilgisayar\u0131m\u0131zda 0xFACE alan\u0131 korunan, \u00f6zel bir bellek alan\u0131 olacakt\u0131r. Yukardaki koddan yaln\u0131zca ibret \u00e7\u0131kar\u0131n\u0131z, kodu bilgisayar\u0131n\u0131zda \u00e7al\u0131\u015ft\u0131rman\u0131za bence pek gerek yok :) \u00c7al\u0131\u015ft\u0131rsan\u0131z da zaten yazma korumas\u0131 oldu\u011fundan kod donacakt\u0131r ve i\u015fletim sistemi taraf\u0131ndan sonland\u0131r\u0131lacakt\u0131r.[\/su_box]\r\n\r\nG\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi muhteremler, sabit adresleri i\u015faret eden i\u015faret\u00e7ileri s\u0131kl\u0131kla kullanaca\u011f\u0131z. \u015eu ana kadar bellekteki bilgiyi hep int8_t olarak anlamland\u0131rd\u0131k. Ger\u00e7ek\u00e7i durumlarda genelde konfig\u00fcrasyonlar mikrokontrol\u00f6r register'lar\u0131nda struct gibi saklan\u0131r. O sebeple struct'\u0131 nas\u0131l sabit bir adrese g\u00f6steririz onu d\u00fc\u015f\u00fcnmekte faydalar var.\r\n\r\nBenzer bir mevzu ama, registeri do\u011frudan i\u015faret eden bir etiket de a\u015fa\u011f\u0131daki gibi tan\u0131mlanabilir:\r\n<pre class=\"lang:c decode:true\">#define NVIC_ST_CTRL_R          (*((volatile uint32_t *)0xE000E010))\r\n#define NVIC_ST_RELOAD_R        (*((volatile uint32_t *)0xE000E014))\r\n#define NVIC_ST_CURRENT_R       (*((volatile uint32_t *)0xE000E018))\r\n#define GPIO_PORTF_DATA_R       (*((volatile uint32_t *)0x400253FC))<\/pre>\r\n&nbsp;\r\n\r\n<strong>Fonksiyon \u0130\u015faret\u00e7ileri (Function Pointers)<\/strong>\r\n\r\nFonksiyon i\u015faret\u00e7ilerinin bir \u00f6rne\u011fini asl\u0131nda karar yap\u0131lar\u0131 yaz\u0131s\u0131nda vermi\u015ftim ama pek a\u00e7\u0131klamam\u0131\u015ft\u0131m. \u015eimdi bu vesileyle bu \u00f6nemli konuyu da bir nebze daha peki\u015ftirme f\u0131rsat\u0131 bulmu\u015f olaca\u011f\u0131z.\r\n\r\nC dilinde fonksiyonlar da esasen bir nevi de\u011fi\u015fkendir. Ancak fonksiyonlar, daha \u00f6nceden de detayl\u0131ca a\u00e7\u0131klad\u0131\u011f\u0131m\u0131z \u00fczere biraz pahal\u0131 de\u011fi\u015fkenlerdir. Bu vesileyle bedeli \u00f6denerek tan\u0131mlanm\u0131\u015f fonksiyonlar\u0131n, ikinci a\u015famada i\u015faret edilmesi ihtiyac\u0131 do\u011fmaktad\u0131r. Hemen \u00f6rne\u011fimizi hat\u0131rlayal\u0131m.\r\n<pre class=\"lang:c decode:true\">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n \r\n#define STATE_DEMO_LOOP_CNT    (10)\r\n \r\ntypedef void (*myStateHandler) (void);\r\n \r\ntypedef enum\r\n{\r\n  E_STATE_NONE=0,\r\n  E_STATE_1,     \r\n  E_STATE_2,\r\n  E_STATE_3,\r\n  E_STATE_4,\r\n  E_STATE_LAST\r\n}E_STATES;\r\n \r\nmyStateHandler myStateList[E_STATE_LAST];\r\nE_STATES e_state;\r\n \r\n \r\nvoid STATE1_HANDLER (void)\r\n{\r\n     printf(\"State1n\"); \r\n     e_state = E_STATE_3;  \r\n}\r\n \r\nvoid STATE2_HANDLER (void)\r\n{\r\n     printf(\"State2n\"); \r\n     e_state = E_STATE_4;  \r\n}\r\n \r\nvoid STATE3_HANDLER (void)\r\n{\r\n     printf(\"State3n\"); \r\n     e_state = E_STATE_2;  \r\n}\r\n \r\nvoid STATE4_HANDLER (void)\r\n{\r\n     printf(\"State4n\"); \r\n     e_state = E_STATE_1;  \r\n}\r\n \r\n \r\nvoid Init()\r\n{\r\n    myStateList[E_STATE_1] =  STATE1_HANDLER;\r\n    myStateList[E_STATE_2] =  STATE2_HANDLER;\r\n    myStateList[E_STATE_3] =  STATE3_HANDLER;\r\n    myStateList[E_STATE_4] =  STATE4_HANDLER;\r\n    e_state = E_STATE_1;\r\n}\r\nint main()\r\n{\r\n    uint8_t bCnt;\r\n    Init();\r\n    \r\n    for(bCnt=0;bCnt&lt;STATE_DEMO_LOOP_CNT;bCnt++)\r\n    {\r\n        myStateList[e_state]();    \r\n    }\r\n    \r\n    while(1); \/\/stop here\r\n    return 0;\r\n }<\/pre>\r\n\u00d6rne\u011fimiz asl\u0131nda ball\u0131 kaymak. Neden? \u00c7\u00fcnk\u00fc fonksiyon i\u015faret\u00e7isini tan\u0131mlamak ile yetinmemi\u015fiz, o \u00f6zel i\u015faret\u00e7i tipini bir de typedef ile tan\u0131mlam\u0131\u015f\u0131z ki, ihtiyac\u0131 olan herkes bu yeni tipten faydalans\u0131n. Bir nevi hayrat yakla\u015f\u0131m\u0131 olmu\u015f. Neyse... Fonksiyon i\u015faret\u00e7isi a\u015fa\u011f\u0131daki gibi tan\u0131mlanm\u0131\u015f:\r\n<pre class=\"lang:c decode:true\"> void (*myStateHandler) (void);<\/pre>\r\nBu yaz\u0131m tipi sabit. \"donusTipi (*isim) (argumanlar)\" \u015feklinde bir kal\u0131b\u0131m\u0131z var. Fonksiyon i\u015faret\u00e7isi b\u00f6yle tan\u0131mlan\u0131yor. Peki buradaki hikmeti ne bu i\u015faret\u00e7inin? Switch-case yerine bunu kulland\u0131k tamam, ayn\u0131 \u015fekilde de \u00e7al\u0131\u015ft\u0131 ama bu mevzunun alt\u0131nda yatan felsefe ne? Nesneye dayal\u0131 programlamada polymorphism yani \u00e7ok \u015fekillilik dedi\u011fimiz mevzun\u0131n C dili ile ger\u00e7eklenmesi asl\u0131nda bu. Yukar\u0131daki kodda her durummun bir durum fonksiyonu var. Bu fonksiyonun \u015fekli \u015femali hepsi i\u00e7in ortak. Ve hangi durum olursa, o durumun fonksiyonu \u00e7a\u011f\u0131r\u0131l\u0131yor. Her biri ayn\u0131 \u015fekilde \u015femalde bu fonksiyonlar\u0131n, hepsini ayn\u0131 i\u015faret\u00e7i i\u015faret ediyor s\u0131rayla ama o anki durum ne ise, o an onun fonksiyonu i\u015faret edildi\u011finden her seferinde ilgili durumun fonksiyonu \u00e7a\u011f\u0131r\u0131lm\u0131\u015f oluyor. Bu da ger\u00e7ek hayat\u0131n modellenmesi konusunda bizlere b\u00fcy\u00fck avantajlar sunuyor.\r\n\r\nFonksiyon i\u015faret\u00e7ilerinin kullan\u0131m alanlar\u0131 elbette ki bununla s\u0131n\u0131rl\u0131 de\u011fil. E\u011fer bir SDK geli\u015ftiriyorsan\u0131z, muhtemelen Callback s\u00f6zc\u00fc\u011f\u00fc ile yat\u0131p, Callback s\u00f6zc\u00fc\u011f\u00fc ile kalkacaks\u0131n\u0131z. Bu callback mevzusunda da fonksiyon i\u015faret\u00e7ileri kullan\u0131l\u0131yor. \u015eimdi diyelim ki SDK geli\u015ftiriyorsunuz ve SDK'da \u00f6zel bir olay oldu\u011funda, kullan\u0131c\u0131n\u0131n size s\u00f6yledi\u011fi bir fonksiyonun \u00e7a\u011f\u0131r\u0131lmas\u0131n\u0131 istiyorsunuz. Yani \u00e7a\u011f\u0131r\u0131lacak fonksiyonu asl\u0131nda bilmiyorsunuz bile. Sadece o olay ger\u00e7ekle\u015ftirildi\u011finde, sisteme kaydedilmi\u015f bir callback var ise o \u00e7a\u011f\u0131r\u0131ls\u0131n istiyorsunuz. Bu i\u015fi nas\u0131l yazar\u0131z?\r\n<pre class=\"lang:c decode:true\" title=\"mysdkfile.h\">#ifndef H_MYSDKFILE\r\n#define H_MYSDKFILE\r\n\r\n#include &lt;stdint.h&gt;\r\n\r\ntypedef void (*fpEventCallback)(void);\r\n\r\n\r\nvoid SDK_RegisterOverflowCallback(fpEventCallback OverflowCallback);\r\n\r\n#endif<\/pre>\r\n<pre class=\"lang:c decode:true\" title=\"mysdkfile.c\">#include \"mysdkfile.h\"\r\n\r\n#define SDK_EVENT_INFO_LIMIT (0x02EA)\r\n\r\nfpEventCallback SdkOvfCallback = NULL;\r\n\r\nvoid SDK_RegisterOverflowCallback(fpEventCallback OverflowCallback)\r\n{\r\n  if(NULL != OverflowCallback)\r\n  {\r\n    SdkOvfCallback = OverflowCallback;\r\n  }\r\n}\r\n\r\nvoid MyEvent(uint32_t eventInfo)\r\n{\r\n if(eventInfo &gt; SDK_EVENT_INFO_LIMIT &amp;&amp; (NULL != SdkOvfCallback))\r\n {\r\n   SdkOvfCallback(); \/\/ call the callback for overflow if it is registered\r\n }\r\n \/\/..\r\n\r\n}<\/pre>\r\n\u015eimdi yukar\u0131da, SDK'y\u0131 yazanlar olarak biz \u00e7i\u00e7ek gibi event callback register mekanizmas\u0131n\u0131 verdik. Art\u0131k MyEvent olay\u0131 geldi\u011finde, e\u011fer olay bilgisi, s\u0131n\u0131r de\u011ferden b\u00fcy\u00fckse, kullan\u0131c\u0131n\u0131n verdi\u011fi herhangi bir fonksiyon \u00e7a\u011f\u0131r\u0131lacak. Bu fonksiyon herhangi bir i\u015f yapabilir, kullan\u0131c\u0131 ne isterse! Ama i\u00e7inde while(1); gibi terbiyesizliklerin olmamas\u0131 laz\u0131m! \u015eimdi SDK'y\u0131 kullanmak isteyen, usturuplu, terbiyeli bir yaz\u0131l\u0131mc\u0131 kendi fonksiyonunu nas\u0131l bizim SDK'ya kaydeder onu yazal\u0131m.\r\n<pre class=\"lang:c decode:true\" title=\"myapp.c\">#include &lt;stdint.h&gt;\r\n#include \"mysdkfile.h\"\r\n\r\nvoid OverflowHandler(void)\r\n{\r\n   printf(\"There is an overflow! Mom, help me!!!rn\");\r\n   \r\n   OverflowFixerFunc();\r\n}\r\n\r\nint32_t main()\r\n{\r\n  InitializeSystem();\r\n\r\n  SDK_RegisterOverflowCallback(OverflowHandler);\r\n\r\n  for(;;)\r\n  {\r\n    DoWhatIsNeeded();\r\n  }\r\n}<\/pre>\r\nG\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi, bir fonksiyona parametre olarak ba\u015fka bir fonksiyonu verdik. :) Bu ibretlik olay\u0131 fonksiyon i\u015faret\u00e7ilerinin varl\u0131\u011f\u0131na bor\u00e7luyuz. Buradan indirilecek ibreti beyinlerimize indirdi\u011fimizi d\u00fc\u015f\u00fcn\u00fcyorum. \u00d6yleyse bir sonraki konuya ge\u00e7ebiliriz.\r\n\r\n<strong>Genel \u0130\u015faret\u00e7i (Void Pointer, void*)<\/strong>\r\n\r\nHi\u00e7 uzatmadan konuya girece\u011fim. C dilinde, bir nevi joker olarak kullanabilece\u011fimiz, her yere yedirebilece\u011fimiz, her \u015feye cast edebilece\u011fimiz bir veri tipi bulunuyor. Bu veri tipi, \u00e7ok a\u00e7\u0131k s\u00f6yl\u00fcyorum void*'d\u0131r. Genel i\u015faret\u00e7i olarak tarif edebilece\u011fimiz bu i\u015faret\u00e7i tipi ile, her \u015feyi i\u015faret edebilirsiniz. Daha do\u011frusu, herhangi bir \u015feyi i\u015faret edebilirsiniz. Bu da bize jenerik kodlama yapma \u015fans\u0131 sa\u011fl\u0131yor.\r\n\r\nDiyelim iki veriyi toplayan bir fonksiyon yazacak olal\u0131m. Her bir veri tipi i\u00e7in ayr\u0131 ayr\u0131 topla fonksiyonu yazmadan nas\u0131l yapar\u0131z bu i\u015fi? T\u00fcm veri tipleri i\u00e7in olmasa da, 32 bite kadar olan standart veri tipleri i\u00e7in \u015f\u00f6yle yapar\u0131z:\r\n<pre class=\"lang:c decode:true\">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\n\/*Maximum 32 bit numbers summation*\/\r\nuint32_t Summation(void* pParam1, void* pParam2 )\r\n{\r\n\tuint32_t retVal;\r\n\r\n   if(NULL != pParam1 &amp;&amp; NULL != pParam2)\r\n   {\r\n     retVal = ((*(uint32_t*)pParam1) + (*(uint32_t*)pParam2));\r\n   }\r\n   return retVal;\r\n}\r\n\r\nint32_t main()\r\n{\r\nint32_t i32Num1 = 29;\r\nint32_t i32Num2 = 11;\r\n\r\nint8_t i8Num1= 5;\r\nint8_t i8Num2= -2;\r\nprintf(\"Summation of int32_t numbers: %d\\r\\n\", (int32_t)Summation(&amp;i32Num1,&amp;i32Num2));\r\nprintf(\"Summation of int8_t numbers: %d\\r\\n\", (int8_t)Summation(&amp;i8Num1,&amp;i8Num2));\r\nreturn 0;\r\n}\r\n<\/pre>\r\nG\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi b\u00fcy\u00fck oranda jenerik bir fonksiyon yazm\u0131\u015f olduk. \u00a0Ayr\u0131ca void i\u015faret\u00e7isini di\u011fer tipteki i\u015faret\u00e7ilere cast etti\u011fimize dikkatinizi \u00e7ekerim. Bu mereti, her tipteki i\u015faret\u00e7iye cast etmek (aktarmak) m\u00fcmk\u00fcn.\r\n\r\n[su_box title=\"Dikkat\" style=\"soft\" box_color=\"#5fb8fa\"]Yukar\u0131daki fonksiyon float veri tipi i\u00e7in do\u011fru \u00e7al\u0131\u015fmayacakt\u0131r. Float veri tipleri, derleyici taraf\u0131ndan IEEE754 format\u0131na uygun olarak -\u00f6zel y\u00f6ntemlerle- sakland\u0131\u011f\u0131ndan ve topland\u0131\u011f\u0131ndan, uint32 format\u0131 \u00fczerinden iki float say\u0131n\u0131n toplanmas\u0131 do\u011fru sonucu vermez. Yukar\u0131daki kodu, profesyonel uygulamalarda kullanmay\u0131n\u0131z.[\/su_box]\r\n\r\nSon olarak k\u0131sa bir hat\u0131rlatma yapay\u0131m. Bir sistemin ka\u00e7 bitlik oldu\u011funu \u00f6\u011frenmek i\u00e7in:\r\n<pre class=\"lang:c decode:true\">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\nint32_t main()\r\n{\r\n\r\nprintf(\"Bu platform %d bitliktirrn\", 8*sizeof(void*));\r\ngetchar();\r\n\r\nreturn 0;\r\n}<\/pre>\r\nBence void* b\u00fcy\u00fck oranda anla\u015f\u0131ld\u0131. \u015eimdi yine her zamanki sevimli hareketlerden birini yapaca\u011f\u0131z. Bilgilerimizi harmanlayaca\u011f\u0131z. Fonksiyon i\u015faret\u00e7ileri ile genel i\u015faret\u00e7ileri birle\u015ftirdi\u011fimizde ne kadar g\u00fc\u00e7l\u00fc bir \u015fey elde etti\u011fimizi d\u00fc\u015f\u00fcnelim.\r\n<pre class=\"lang:default decode:true\">typedef void (*DataSendOverSerial)(void* pData, in32_t lenInBytes);<\/pre>\r\nYukar\u0131daki fonksiyon i\u015faret\u00e7isi tipi, giri\u015f parametresi olarak genel i\u015faret\u00e7iyi al\u0131yor. Yukar\u0131daki fonksiyon tipindeki bir fonksiyon, tip ayr\u0131m\u0131 yapmaks\u0131z\u0131n her t\u00fcrl\u00fc veriyi seri porttan g\u00f6nderebilir. Float olsun, int olsun, char olsun, int32_t olsun, hatta ve hatta bir fonksiyonu bile seri port \u00fczerinden g\u00f6nderebilirsiniz :) Ve ayn\u0131 zamanda size polimorfik bir yap\u0131 sunar. K\u0131zarm\u0131\u015f ekmek \u00fcst\u00fcnde bal kaymak gibi... Mis.. Afiyet olsun :) \u00d6yleyse devam!\r\n\r\n<strong>K\u0131saltma \u0130\u00e7in \u0130\u015faret\u00e7iler<\/strong>\r\n\r\nC dilinde, kompleks veri yap\u0131lar\u0131 diye bir mevzu var. \u0130lk ba\u015fta \u015faka gibi geliyor bu ifade ama baz\u0131 veri yap\u0131lar\u0131 hakikaten kompleks olabiliyor :) Bir sturct i\u00e7inde ba\u015fka bir struct, onun i\u00e7inde afedersiniz ba\u015fka bir struct, onun i\u00e7inde de bir i\u015faret\u00e7i d\u00fc\u015f\u00fcnelim. Bu durumda en alt seviyedeki de\u011fikene ula\u015fmak hakikaten baya\u011f\u0131 zaman alacakt\u0131r. \u00d6zellikle tembel yaz\u0131l\u0131mc\u0131lar\u0131, klavyede bu kadar tu\u015fa basmaktan nefret ederler. Bu gibi durumlarda da k\u0131saltma ama\u00e7l\u0131 olarak i\u015faret\u00e7ilerden faydalanabiliriz. Misal:\r\n<pre class=\"lang:c decode:true \">typedef struct\r\n{\r\n  int8_t test1;\r\n  int8_t mest1;\r\n  int8_t jest1;\r\n  int8_t kest1;\r\n  int8_t lest1;\r\n}s_Struct3;\r\n\r\n\/\/myStruct3'\u00fcn tipi s_Struct3* olsun.\r\nagaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3-&gt;test1 = 1;\r\nagaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3-&gt;mest1 = 2;\r\nagaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3-&gt;jest1 = 3;\r\nagaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3-&gt;kest1 = 4;\r\nagaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3-&gt;lest1 = 5;\r\n\r\n\/\/yazmak yerine;\r\ns_Struct3* kucukStruct3;\r\nkucukStruct3 = agaogluMyStruct0.myStruct1.myStruct2[index]-&gt;myStruct3;\r\nkucukStruct3-&gt;test1 = 1;\r\nkucukStruct3-&gt;mest1 = 2;\r\nkucukStruct3-&gt;jest1 = 3;\r\nkucukStruct3-&gt;kest1 = 4;\r\nkucukStruct3-&gt;lest1 = 5;\r\n\/\/yazmak suphesiz daha kisa oluyor<\/pre>\r\n\u0130lk bak\u0131\u015fta komik bir kullan\u0131m alan\u0131 gibi g\u00f6z\u00fckse de, i\u015fin i\u00e7ine girdi\u011fimizde bu tip kullan\u0131mlar\u0131n yads\u0131namaz miktarda oldu\u011funu g\u00f6r\u00fcyoruz. Belki de tembelli\u011fin b\u00f6ylesi cand\u0131r canand\u0131r :) Tabi burada bir pointer'\u0131 ekstradan kullanarak bellekten biraz \u00e7ald\u0131k. De\u011fer mi de\u011fmez mi o karar\u0131 size b\u0131rak\u0131yorum.\r\n\r\n<strong>Diziler ve \u0130\u015faret\u00e7iler<\/strong>\r\n\r\nDiziler ve i\u015faret\u00e7iler birbirlerine \u00e7ok \u00e7ok yak\u0131n iki kavramd\u0131r. Nihayetinde her bir dizi, asl\u0131nda bir i\u015faret\u00e7idir. Ancak bu \u00f6zel i\u015faret\u00e7iler tan\u0131mlan\u0131rken, i\u015faret edecekleri bellek alanlar\u0131 \u00f6nceden ayr\u0131l\u0131r.\r\n\r\nDiziler de t\u0131pk\u0131 di\u011fer de\u011fi\u015fkenler gibi ilk de\u011fer atamas\u0131 mevzular\u0131na tabidir. \u0130lk de\u011fer atamas\u0131 yap\u0131lmam\u0131\u015f bir dizi tan\u0131m\u0131 a\u015fa\u011f\u0131daki gibidir:\r\n<pre class=\"lang:c decode:true \">uint8_t u8TestArray[10];<\/pre>\r\nBurada yaln\u0131zca dizinin 10 elemanl\u0131 olaca\u011f\u0131 bilgisi verilmi\u015f. yani u8TestArray de\u011fi\u015fkeninin i\u015faret etti\u011fi bellek adresinden ba\u015flamak \u00fczere 10 byte bu dizinin elemanlar\u0131 olarak s\u0131ralanacak.\r\n\r\n\u015eimdi ilk de\u011fer atamas\u0131 yap\u0131lm\u0131\u015f ancak boyut verilmemi\u015f bir diziye bakal\u0131m.\r\n<pre class=\"lang:c decode:true\">int8_t testArray[] = \"Hello!\";<\/pre>\r\nBurada test array asl\u0131nda bildi\u011fimiz i\u015faret\u00e7idir. G\u00f6rd\u00fc\u011f\u00fcn\u00fcz \u00fczere kendisine \"Hello!\" \u015feklindeki karakter dizisini yani \u00a0string'i atam\u0131\u015f olduk. C dilinde string, ayr\u0131 bir tip de\u011fildir ancak karakterlerden olu\u015fan bir dizidir. Nitekim yukar\u0131dakinin bir benzeri \u015f\u00f6yledir:\r\n<pre class=\"lang:default decode:true\">int8_t *testPtr = (int8_t*) \"Hello!\";<\/pre>\r\ntestArray dedi\u011fimiz \u015fey asl\u0131nda \u015fu a\u015fa\u011f\u0131daki ile ayn\u0131d\u0131r:\r\n<pre class=\"lang:default decode:true \">&amp;testAray[0];<\/pre>\r\n\u00c7\u00fcnk\u00fc dizinin ismi yani de\u011fi\u015fken ad\u0131 (testArray), asl\u0131nda dizinin ilk eleman\u0131n\u0131n adresini ta\u015f\u0131r (&amp;testArray[0]).\r\n\r\n\u0130\u015fte bunun fark\u0131nda olmakta ve bunu unutmamakta faydalar var.\r\n\r\nYukar\u0131daki \u00f6rnekte verdi\u011fimiz Hello! yaz\u0131s\u0131n\u0131 karakter karakter yazd\u0131rmak istesek dizinin her bir eleman\u0131n\u0131 yazd\u0131rabilece\u011fimiz gibi, pointer aritmeti\u011fi \u00a0ile de ayn\u0131 i\u015fi yapabiliriz.\r\n<pre class=\"lang:c decode:true \">#include &lt;stdint.h&gt;\r\n#include &lt;stdio.h&gt;\r\n\r\n\r\nint32_t main()\r\n{\r\nint8_t* testPtr = (int8_t*)\"Hello!\";\r\n\r\nwhile(*testPtr)\r\n{\r\n    printf(\"%c\",*testPtr++);\r\n}\r\ngetchar();\r\n  return 0;\r\n}<\/pre>\r\n<strong>Struct ve \u0130\u015faret\u00e7iler<\/strong>\r\n\r\nYap\u0131lar ba\u015fl\u0131kl\u0131 yaz\u0131mda esasen bu konuya de\u011finmi\u015ftim ancak ufaktan tekrar etmekte fayda var diye d\u00fc\u015f\u00fcn\u00fcyorum. Struct genelde kocaman bir yap\u0131y\u0131 modelledi\u011finden bellekte kaplad\u0131\u011f\u0131 yer ciddiye al\u0131nmal\u0131d\u0131r. Hal-i haz\u0131rda k\u00fc\u00e7\u00fcc\u00fck olup ciddiye almad\u0131\u011f\u0131n\u0131z bir struct, yaz\u0131l\u0131m\u0131n bir sonraki versiyonunda b\u00fcy\u00fcyebilir ve size ciddiye almak zorunda kalaca\u011f\u0131n\u0131z baz\u0131 problemler yaratabilir. O sebeple sayg\u0131y\u0131 ba\u015ftan g\u00f6stermekte faydalar var.\r\n\r\nBir struct tan\u0131mland\u0131ktan ve onunla ilgili bilgi belle\u011fe yaz\u0131ld\u0131ktan sonra, o veriyi kullanmak i\u00e7in ba\u015fka bir sturct yaratmak \u00e7o\u011fu durumda anlams\u0131z ve mant\u0131ks\u0131zd\u0131r. Onun yerine struct i\u015faret\u00e7isi tan\u0131mlanarak, ilgili struct'\u0131 i\u015faret edecek \u015fekilde de\u011fer atamas\u0131 yap\u0131lmas\u0131nda say\u0131s\u0131z faideler ve feyizler vard\u0131r.\r\n\r\n<strong>Union ve \u0130\u015faret\u00e7iler<\/strong>\r\n\r\nUnion bildi\u011finiz \u00fczere; her eleman\u0131 belle\u011fin ayn\u0131 adresini g\u00f6steren \u00f6zel bir yap\u0131. Kendisinin feyizli \u00f6zelliklerini sizlerle payla\u015fm\u0131\u015ft\u0131k. Ancak tan\u0131m\u0131ndan da anla\u015f\u0131labilece\u011fi \u00fczere kendisi asl\u0131nda bir \u00e7e\u015fit \u00f6zel i\u015faret\u00e7idir. Dolay\u0131s\u0131yla union kullanarak yapabilece\u011fimiz bir \u00e7ok i\u015fi, \u00e7ok daha \u00e7irkin \u015fekilde do\u011frudan i\u015faret\u00e7ilerle de yapabiliriz. Misal:\r\n<pre class=\"lang:c decode:true \">uint32_t nRead;\r\n   uint32_t index;\r\n   typedef union {\r\n       uint32_t u32Data;\r\n       int16_t  as16Data[2];\r\n       int8_t   as8Data[4];\r\n   }tu_DataGroup32;\r\n \r\n   tu_DataGroup32 UData;\r\n   \/\/ ( Code to read in nRead, from the user or a file, has been omitted in this example )\r\n    UData.u32Data = nRead;\r\n    for(  index= 0; index &lt; sizeof(uint32_t); index++ )\r\n    {\r\n        printf( \"Byte number %d of %ud is %udn\", index, nRead, UData.as8Data[index] );\r\n    }<\/pre>\r\nyerine benzer i\u015fi yapan \u015f\u00f6yle bir kod da yazabiliriz.\r\n<pre class=\"lang:c decode:true\">uint32_t nRead;\r\n   uint32_t index;\r\n\r\n    for(  index= 0; index &lt; sizeof(uint32_t); index++ )\r\n    {\r\n        printf( \"Byte number %d of %ud is %udn\", index, nRead, (*(int8_t*)((&amp;nRead) + index)) );\r\n    }<\/pre>\r\nAma dedi\u011fim gibi \u00e7irkin olur kem olur. Parantez manya\u011f\u0131 olmak zorunda kal\u0131r\u0131z ve kodumuz da anla\u015f\u0131lmaz.\r\n\r\nAncak yine de olay\u0131n alt\u0131nda yatan felsefeyi bilmekte faideler var.\r\n\r\n<strong>NULL \u0130\u015faret\u00e7isi<\/strong>\r\n\r\nBu NULL denen nane \u00e7ok me\u015fhurdur, her yerde de kullan\u0131l\u0131r. NULL i\u015faret\u00e7isi esasen belle\u011fin 0 numaral\u0131 adresini g\u00f6steren bir i\u015faret\u00e7idir. Kendisinin tipi void*'d\u0131r.\r\n\r\nK\u00fct\u00fcphanelerdeki (stddef.h) tan\u0131m\u0131na bakt\u0131\u011f\u0131m\u0131z zaman \u015funu g\u00f6r\u00fcr\u00fcr\u00fcz:\r\n<pre class=\"lang:c decode:true \">#define NULL ((void*) 0)<\/pre>\r\nNULL dedi\u011fimiz nane i\u015fte budur. Belle\u011fin 0 nolu b\u00f6lgesini g\u00f6steren bir i\u015faret\u00e7i. Peki neden bir i\u015faret\u00e7inin \"bo\u015f\" olup olmad\u0131\u011f\u0131n\u0131 kontrol etmek i\u00e7in bunu kullan\u0131r\u0131z? \u00c7\u00fcnk\u00fc bir i\u015faret\u00e7i ilk de\u011fer atamas\u0131 yap\u0131lana kadar s\u0131f\u0131r nolu bellek adresini g\u00f6sterir. Dolay\u0131s\u0131yla bu ona ilk de\u011fer atamas\u0131 yap\u0131lmad\u0131\u011f\u0131n\u0131 anlaman\u0131n g\u00fczel bir yoludur.\r\n\r\n<strong>Fonksiyonlara Arg\u00fcman\u00a0Olarak\u00a0\u0130\u015faret\u00e7iler<\/strong>\r\n\r\nFonksiyonun pahal\u0131 bir de\u011fi\u015fken oldu\u011funu her f\u0131rsatta s\u00f6yl\u00fcyorum, s\u00f6ylemeye de devam edece\u011fim. \u015eimdi bu pahal\u0131l\u0131kta \u00f6nemli bir gider kalemi de fonksiyonlar\u0131n arg\u00fcmanlar\u0131d\u0131r. Bir fonksiyonun arg\u00fcmanlar\u0131 belle\u011fin \u00f6zel bir b\u00f6lgesine kopyalan\u0131r. S\u00f6z\u00fc uzatmadan mevzuya dalaca\u011f\u0131m. E\u011fer kopyalanan \u015fey devasa bir struct ise vay halinize. Ne demi\u015ftik? Struct kopyalamak \u00e7o\u011fu durumda mant\u0131ks\u0131zd\u0131r. Demek ki fonksiyona arg\u00fcman olarak struct yerine struct i\u015faret\u00e7isini vermekte fayda var. Bu ayn\u0131 zamanda fonksiyonun kullanaca\u011f\u0131 belle\u011fin, fonksiyonu \u00e7a\u011f\u0131racak ki\u015fi taraf\u0131ndan ayr\u0131lmas\u0131na (allocate etmek) izin verdi\u011finden, (caller allocation prensibi) fevkalade lezzetli bir olayd\u0131r.\r\n\r\nBu mevzu hakk\u0131nda detayl\u0131 bilgiyi ve \u00f6rnek kodlar\u0131 <a href=\"http:\/\/ozenozkaya.com\/blog\/?p=286\" target=\"_blank\" rel=\"noopener\">BURADAN<\/a>, \"<strong>Struct\u2019lar\u0131n\u00a0Pointer(\u0130\u015faret\u00e7i) ile \u0130mtihan\u0131\"\u00a0<\/strong>ba\u015fl\u0131kl\u0131 b\u00f6l\u00fcmden bulabilirsiniz.\r\n\r\nFonksiyonlara arg\u00fcman olarak i\u015faret\u00e7i verilmesinin bir di\u011fer \u00f6nemli kullan\u0131m alan\u0131 da, o fonksiyonun arg\u00fcman\u0131n\u0131 fonksiyon i\u00e7inde de\u011fi\u015ftirmesine olanak vermektir. Bu \u00f6zellik yads\u0131namaz derecede \u00f6nemlidir. Her fonksiyon tek i\u015f yapmal\u0131d\u0131r demi\u015ftik ama baz\u0131 durumlarda bir fonksiyonun birden fazla de\u011fer d\u00f6nd\u00fcrmesi gerekebilir. \u00d6yleyse o de\u011ferlerin arg\u00fcmanlarda i\u015faret\u00e7i olarak al\u0131nmas\u0131 yeterli olacakt\u0131r \u00e7\u00fcnk\u00fc bir kez de\u011fi\u015fkenin adresi bilindi mi, onun i\u00e7indeki veriyi man\u00fcple etmek problem olmayacakt\u0131r :)\r\n\r\nHemen k\u0131sa bir \u00f6rnek vereyim:\r\n<pre class=\"lang:default decode:true\">#include &lt;stdio.h&gt;\r\n#include &lt;stdint.h&gt;\r\n\r\nvoid Function1(int8_t a);\r\nvoid Function2(int8_t* a);\r\n\r\nint32_t main()\r\n{\r\nint8_t a = 55;\r\nprintf(\"a'nin degeri %drn\",a);\r\n Function1(a);\r\nprintf(\"a'nin degeri %drn\",a);\r\nFunction2(&amp;a);\r\nprintf(\"a'nin degeri %drn\",a);\r\n\r\ngetchar();\r\nreturn 0;\r\n}\r\n\r\n\r\nvoid Function1(int8_t a)\r\n{\r\n  a++;\r\n  printf(\"%s icinde a'nin degeri %drn\",__FUNCTION__,a);\r\n}\r\nvoid Function2(int8_t* a)\r\n{\r\n  (*a)++;\r\n  printf(\"%s icinde a'nin degeri %drn\",__FUNCTION__,*a);\r\n}<\/pre>\r\nBu kod \u00e7al\u0131\u015ft\u0131r\u0131ld\u0131\u011f\u0131nda \u00e7\u0131kt\u0131s\u0131 \u015f\u00f6yle olur:\r\n\r\n[su_box title=\"Konsol \u00c7\u0131kt\u0131s\u0131\" style=\"soft\" box_color=\"#2cf828\"]a'nin degeri 55\r\nFunction1 icinde a'nin degeri 56\r\na'nin degeri 55\r\nFunction2 icinde a'nin degeri 56\r\na'nin degeri 56\r\n\r\n--------------------------------\r\nProcess exited with return value 0\r\nPress any key to continue . . .\r\n[\/su_box]\r\n\r\nG\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi Fonksiyon1, a de\u011fi\u015fkenini fonksiyonun d\u0131\u015f\u0131nda etkili olacak \u015fekilde de\u011fi\u015ftirememi\u015f, ancak Fonksiyon2 de\u011fi\u015ftirebilmi\u015ftir. Bunun sebebi asl\u0131nda basittir, Fonksiyon1 a de\u011fi\u015fkeninin kendisini de\u011fil, adi bir kopyas\u0131n\u0131 de\u011fi\u015ftirmi\u015ftir. Nitekim a'lar\u0131n adresleri yazd\u0131r\u0131lsa farkl\u0131 \u00e7\u0131kacakt\u0131r. Bu merete Japonlar bunshin diyor :D Bilenler bilir.\r\n\r\n<strong>Komut Sat\u0131r\u0131 Giri\u015fi<\/strong>\r\n\r\nSon olarak, komut sat\u0131r\u0131 arg\u00fcmanlar\u0131ndan bahsedece\u011fim. Bu, g\u00f6m\u00fcl\u00fc sistemlerde \u00e7ok da \u00f6nemli de\u011fil ancak bilmekte faydalar var.\r\n<pre class=\"lang:c decode:true \">int main( int argc,char * argv[ ] );\r\nint main( int argc, char **argv );<\/pre>\r\nYukar\u0131dakiler hemen hemen ayn\u0131 mevzular. Siz yazd\u0131\u011f\u0131n\u0131z kodu derleyip konsoldan \u00e7a\u011f\u0131rd\u0131\u011f\u0131n\u0131zda ona parametre verebilirsiniz. Bunun ad\u0131 komut sat\u0131r\u0131 arg\u00fcmanlar\u0131d\u0131r ve program \u00e7a\u011f\u0131r\u0131l\u0131rken bu bilgi programa verilebilir. G\u00f6m\u00fcl\u00fc sistemlerde kodu komut sat\u0131r\u0131ndan \u00e7a\u011f\u0131rmad\u0131\u011f\u0131n\u0131zdan bu olay bu ama\u00e7la kullan\u0131lmaz ama ba\u015fka ama\u00e7larla kullan\u0131labilir :) \u00d6nemli olan mevzu \u015fudur; verdi\u011finiz arg\u00fcmanlar aras\u0131ndaki bo\u015fluk bulunan kelimelerdir. Bu kelimelerin say\u0131s\u0131 argc'ye, kendileri de argv'ye i\u015fletim sistemi taraf\u0131ndan aktar\u0131l\u0131r.\r\n\r\nHemen \u00e7ok s\u0131k verilen \u015fu kodu biz de \u00f6rnek olarak verelim:\r\n<pre class=\"lang:c decode:true \">#include&lt;stdio.h&gt;\r\n\r\nint main(int argc,char **argv)\r\n{\r\nint i;\r\nfor(i=0;i&lt;argc;i++)\r\n{\r\nprintf(\u201c%sn\u201d,argv[i]);\r\n}\r\nreturn 0;\r\n}<\/pre>\r\nBu kodu selam.c olarak kaydedip derledi\u011fimizi, ve \u00e7\u0131kt\u0131\u00a0olan program\u0131n ad\u0131n\u0131n\u00a0da selam oldu\u011funu d\u00fc\u015f\u00fcn\u00fcyorum. Komut sat\u0131r\u0131ndan program\u0131 \u015f\u00f6yle \u00e7a\u011f\u0131ral\u0131m \"selam kardes kafan cok guzelmis nerden aldin?\"\r\n\r\nBu durumda komut sat\u0131r\u0131na girilen arg\u00fcman say\u0131s\u0131 argc = 7 olacakt\u0131r. argv[0]'\u0131n g\u00f6sterdi\u011fi yerde program\u0131n ad\u0131 yani selam yazacakken argv[1]'in g\u00f6sterdi\u011fi yerde kardes yazacakt\u0131r. Dolay\u0131s\u0131yla bu kodun \u00e7\u0131kt\u0131s\u0131 \u015f\u00f6yle olur:\r\n\r\n[su_box title=\"Konsol \u00c7\u0131kt\u0131s\u0131\" style=\"soft\" box_color=\"#2cf828\"]selam\r\nkardes\r\nkafan\r\ncok\r\nguzelmis\r\nnerden\r\naldin?\r\n[\/su_box]\r\n\r\n<strong>S\u0131k Yap\u0131lan Hatalar<\/strong>\r\n\r\nArkada\u015flar i\u015faret\u00e7ilerin bili\u00e7siz kullan\u0131mas\u0131 \u00e7ok say\u0131da hataya yol a\u00e7abilir ve bunlar ger\u00e7ekten zorlu hatalar olacakt\u0131r. Ancak sizler, i\u015faret\u00e7ileri buradaki bilgilerle birlikte kulland\u0131\u011f\u0131n\u0131zda bu sorunlar\u0131 zaten ya\u015famayacaks\u0131n\u0131z :)\r\n\r\n*Misal a\u015fa\u011f\u0131daki gibi bir kod yazmayaca\u011f\u0131n\u0131z\u0131 umuyorum:\r\n<pre class=\"lang:c decode:true\">int32_t * ptr , m = 100 ;\r\n      ptr = m ;       \/\/eyvah! dogrusu ptr = &amp;m olacak!<\/pre>\r\n*Bir di\u011fer hata da ilk de\u011fer atanmam\u0131\u015f bir i\u015faret\u00e7inin g\u00f6stermedi\u011fi belle\u011fin i\u00e7ine bir \u015feyler yazmaya \u00e7al\u0131\u015fmakt\u0131r. Kemdir, puan g\u00f6t\u00fcr\u00fcr, yapmay\u0131n\u0131z. Misal:\r\n<pre class=\"lang:c decode:true\">int32_t * ptr , m = 100 ;\r\n*ptr = m ;            \/\/ eyvah! daha ptr'nin nereyi g\u00f6sterdi\u011fi belli degil<\/pre>\r\nDaha ptr'nin nereyi g\u00f6sterdi\u011fini ayarlamadan, bu belle\u011fin i\u00e7ine m'nin de\u011ferini yazmaya \u00e7al\u0131\u015f\u0131yoruz. \u00d6nce bu ptr bir yeri g\u00f6stermeli. Misal:\r\n<pre class=\"lang:default decode:true\">int32_t * ptr;\r\nint32_t m = 100 ,n = 20;\r\nptr = &amp;n;\r\n*ptr = m ;<\/pre>\r\n*Di\u011fer bir hata da, bir i\u015faret\u00e7inin, ilk de\u011fer atanmam\u0131\u015f bir de\u011fi\u015fkeni i\u015faret etmeye \u00e7al\u0131\u015fmas\u0131d\u0131r. Bu \u015f\u0131k bir kullan\u0131m de\u011fildir. \u00d6nce i\u015faret edilecek de\u011fi\u015fkene ilk de\u011fer atamakta faydalar vard\u0131r.\r\n<pre class=\"lang:c decode:true\">int32_t *ptr,\r\nint32_t m;\r\nptr = &amp;m;<\/pre>\r\n*\u0130ki i\u015faret\u00e7iyi kar\u015f\u0131la\u015ft\u0131rmak da iyi bir fikir say\u0131lmaz. \u0130\u015faret\u00e7iler, bellekteki rastgele alanlar\u0131 g\u00f6sterece\u011finden, i\u015faret\u00e7ileri do\u011frudan kar\u015f\u0131la\u015ft\u0131rmak anlams\u0131zd\u0131r. Anlaml\u0131 olabilecek \u015fey, bunlar\u0131n g\u00f6sterdi\u011fi de\u011ferleri kar\u015f\u0131la\u015ft\u0131rmakt\u0131r.\r\n\r\n&nbsp;\r\n<pre class=\"lang:default decode:true \">char str1[10],str2[10];\r\nchar *ptr1 = str1;\r\nchar *ptr2 = str2;\r\n\r\nif(ptr1 &gt; ptr2)  .....   \/\/ Eyvah\r\n{\r\n....\r\n....\r\n}\r\n\r\n\r\nif(*ptr1 &gt; *ptr2)  .....   \/\/ Eyvallah\r\n{\r\n....\r\n....\r\n}<\/pre>\r\nDaha bunu s\u0131ralamakla bitmez ama siz anlad\u0131n\u0131z mevzuyu.\r\n\r\nYaz\u0131lar\u0131 be\u011fendiyseniz e\u011fer, \u00a0faydalanabilecek arkada\u015flar\u0131n\u0131zla da payla\u015fabilirseniz sevinirim.\r\n\r\n\u015eimdi devam...\r\n\r\n[su_button url=\"http:\/\/ozenozkaya.com\/blog\/?p=294\" style=\"3d\"\u00a0icon=\"icon: arrow-circle-o-left\"]\u00d6nceki Sayfa[\/su_button] \u00a0[su_button url=\"http:\/\/ozenozkaya.com\/blog\/\" style=\"3d\" icon=\"icon: arrow-circle-right\"]Sonraki Sayfa[\/su_button]","_tr_post_name":"gomulu-sistemler-25-gomulu-c-isaretciler-2","_tr_post_excerpt":"","_tr_post_title":"G\u00f6m\u00fcl\u00fc C - 14 : \u0130\u015faret\u00e7iler 2","_en_post_content":"","_en_post_name":"","_en_post_excerpt":"","_en_post_title":"","edit_language":"tr","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"enabled":false},"version":2}},"categories":[2,3],"tags":[],"class_list":["post-305","post","type-post","status-publish","format-standard","hentry","category-elektronik","category-gomulu-sistemler"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5gWM6-4V","jetpack-related-posts":[],"_links":{"self":[{"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/305","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=305"}],"version-history":[{"count":5,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/305\/revisions"}],"predecessor-version":[{"id":602,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/305\/revisions\/602"}],"wp:attachment":[{"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=305"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ozenozkaya.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}