C Programlama diliyle şamatalar

Başlatan z, 23 Ekim 2011, 15:32:04

muhittin_kaplan

Kodları deşmeye devam ozaman, Bakmadım Ama Global ve yerel aynı tanımlama yapılmışsa

int Deger;

fonction()
{
float Deger;
Deger=Z/A;
}

Yaparsam benim mantığım fonksiyon içerisindeki ni işleme koyar diyor. Yarın Biraz daha deşeleyip bakayım. 

AsHeS

Alıntı yapılan: muhittin_kaplan - 23 Ocak 2013, 17:49:19
Kodları deşmeye devam ozaman, Bakmadım Ama Global ve yerel aynı tanımlama yapılmışsa

int Deger;

fonction()
{
float Deger;
Deger=Z/A;
}

Yaparsam benim mantığım fonksiyon içerisindeki ni işleme koyar diyor. Yarın Biraz daha deşeleyip bakayım.
Fonksiyon içerisinde fonksiyonda ki Deger değişkenini kullanır fakat fonksiyon dışında mesela main gövdesinde Deger değişkeni çağrılırsa global tanımlanan kullanılır.

muhittin_kaplan

#392
kalın bir main dosyam var, tüm fonksiyonları yazdım buraya. bunu bölmek istiyorum dosyalar halinde yapmam gereken adımlar nelerdir.

int topla(int a, int b)
{
int z=a+b;
return z;
}

int cikart(int a, int b)
{
int z=a-b;
return z;
}

int carp(int a, int b)
{
double z=a*b;
return z;
}


main()
{
int deger;
deger=Topla(1,2);
int DigerDeger=cikart(3,2);
double carpim=carp(2,3);
}


yapmak istediğim matematik.c ve matematik.h adında iki dosya oluşturup bu işlemleri oraya atmak ve main e oradan çağırmak.

mistek

matematik.c

#include stdint.h
#include matematik.h

int topla(int a, int b)
{
int z=a+b;
return z;
}

int cikart(int a, int b)
{
int z=a-b;
return z;
}

int carp(int a, int b)
{
double z=a*b;
return z;
}


matematik.h

#ifndef   MATEMATIK_H_
#define  MATEMATIK_H_

extern int topla(int a, int b);
extern int cikart(int a, int b);
extern int carp(int a, int b);

#endif   //MATEMATIK_H_


boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R

Klein

1. matematik rutinlerini matematik.c dosyasına at.

#include "matematik.h"

int topla(....)
{
..
..
}

long carp(...)
{
..
..
}

..
..

vs..
vs...


matematik rutinleri için header dosya hazırla

matematik.h

#ifndef  __MATEMATIK_H   //(çakışma kilidi)
#define __MATEMATIK_H

#incude "xxxxxx" // ihtiyacın olan dosyaları include et
#include"yyyyyy"
int topla(...);
long carp(..);
..
..

#endif


matematik.c dosyasını projeye dahil et.

main içinde "matematik.h" dosyasını include et.

muhittin_kaplan

#ifndef  __MATEMATIK_H   //(çakışma kilidi)
#define __MATEMATIK_H

Bunun amacı nedir hocam

Tagli

"Header guard" olarak bilinir. Aynı header'ın iki kez include edilmesini engeller. Yani program içinde hiç düşünmeden istenildiği kadar #include "matematik.h" yazılabilir, çünkü sadece bir kez include işlemi yapılacaktır.

O kısım ilk çalıştığında __MATEMATIK_H tanımlı mı diye bakar. Tanımlı değilse bu ifadeyi tanımlar ve altındaki işlemleri yapar. İkinci eklemede __MATEMATIK_H zaten önceden tanımlanmış olduğundan dosyadaki herşey atlanır.

Son satırdaki #endif ifadesini unutmamak lazım tabi. #ifndef bloğunu o kapatıyor.
Gökçe Tağlıoğlu

Klein

Diyelim ki birden fazla dosyada  "matematik.h" include edilmiş.
Şöyle bir kurgumuz olsun.
adc.h
#include "matematik.h"

pwm.h
#include "matematik.h"

main.c (veya main.h)
#include "adc.h"
#include "pwm.h"


main.c derlenirken matematik.h içerisindeki tanımlamalar dosyaya iki kez eklenecekti. Önce adc.h çözümlenirken, sonra da pwm.h çözümlenirken  "matematik.h" içerisindeki tanımlar dosyaya eklenecekti.
bunu çözmek için  çakışma kilidi koymamız gerekecek.
nasıl? 
eğer derleme esnasında bir dosya bir kez include edilmiş ve buradaki tanımlar alınmışsa, bir daha bu tanımların alınmasına engel olarak.

#ifndef __MATEMATIK_H
#define __MATEMATIK_H
..
..
#endif


#ifndef eğer tanımlanmamışsa (no define) anlamına geliyor.
bu kodparçacığı ise 
eğer __MATEMATIK_H tanımını daha önce görmedi isen, bu bloğu derlemeye dahil et. yoksa bu bloğu hiç görmemişsin say anlamına geliyor. Eğer bu tanım daha önce görülmemişse , bu blok derlemeye dahil edileceği için, #define __MATEMATIK_H ile artık tanımlı hale getiriyoruz. Yani derleyiciye sen bu tanımlamaları daha önce gördün diyoruz. 

burada tanımın __MATEMATIK_H olmasının bir nemi yok. #ifndef _MERHABA_DUNYALI_ diyebilirdik. hiç bir şey farketmezdi. dosya adı ile uyumlu olması, anlaşılırlık nedenyle gelenek olmuş. 

derleyici "adc.h" dosyasını işlerken "matematik.h" dosyasının içeriğini okudu. baktı ki __MATEMATIK_H diye bir tanım daha önce yapılmamış. Bloğu derlemeye dahil etti.
sonra "pwm.h" dosyasını işlemeye baladı. baktı ki "matematik.h" dosyası include edilmiş. hemen dosyayı açtı.

#ifndef  __MATEMATIK_H satırına geldi. __MATEMATIK_H dite bir tanım daha önce yapılmış mı diye baktı listesine. Gördü ki bu tanım daha nce yapılmış, bu bloğa eleşmeden #endif satırını aradı ve yoluna oradan devam etti.   

muhittin_kaplan

Bu konularda eksiğim.
Bazı Sormak istediklerime de cevap olmuş.

main.c nin içeriği

adc.h
pwm.h
matematik.h
----------
pwm.h içeriği
include matematik.h
--------------------
adc.h içeriği
include matematik.h

şeklinde olduğundan aslında main.c tarafından matematik.h dolayısıyla matematik.c fonksiyonları defaten çağrılmış ve derlenmiş oluyor. Bu Hatayı düzeltmek için matematik.h dosyasına

#ifndef  __MATEMATIK_H   //(çakışma kilidi)
#define __MATEMATIK_H

#include dosyalar
prototipler......
#endif

yapıyoruz. Buraya kadar tamam.
Şimdi birşey daha sorabilirmiyim, Bir dosyayı include ettiğimde kullandığım fonksiyonumu yoksa tümünümü derler ? Birsürü fonksiyondan oluşmuş bir dosyada bir fonksiyon kullanıyorsa diğrelerinin derlenmesi sistemde fazladan yer kapsamasına neden olmaz mı ?


Klein

Tüm fonksiyonlar derlenir. Ancak link esnsında ve sonrasında sadece kullanılan fonksiyonlar hex koda dönüşür. 

mufitsozen

Alıntı YapŞimdi birşey daha sorabilirmiyim, Bir dosyayı include ettiğimde kullandığım fonksiyonumu yoksa tümünümü derler ? Birsürü fonksiyondan oluşmuş bir dosyada bir fonksiyon kullanıyorsa diğrelerinin derlenmesi sistemde fazladan yer kapsamasına neden olmaz mı ?

olur. Her obj(ect) dosyasinin icindekiler birlikte yuklenir/yerlestirilir.

bunu engellemek icin her fonksiyonu ayri bir dosyaya yerlestirin ve derlenmis object dosyalarini bir lib(rarye) koyun. Link asamasinda bu library kullanilarak referans edilen ama daha yuklenmemis butun fonksiyonlarin obj'leri lib(rary)den aranir ve eklenir.

Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

ilhan_mkp

#401

bu stm32 ile sin(x) olayına basit bir örnek verebilirmisin.



Mucit23

Keilde tanımladığım bir fonksiyonun sonunda bir etiket tanımlıyorum.

fonksiyon içerisinde farklı yerlerden bu etikete goto ile dallanmam gerekiyor.

Böyle yaptığımda kod çalışıyor ama bir uyarı veriyor

src\main.c(2720): warning:  #127-D: expected a statement

Bu uyarının sebebi nedir. Benden ne gibi bir açıklama bekliyor?

armsistem

#403
Keil C anlayamadığım bazı komut satırları var konu hakkında yardımlarınızı bekliyorum.


# define IAP_LOCATION 0X7ffffff1
unsigned long command[5];
unsigned long result[2];

typedef void (*IAP) (unsigned long[],unsigned long[]);


typedef eski_adi yeni_adi şeklinde kullanılıyor ama yukarıda tam olarak ne yapılmak istenildiğini anlayamadım *IAP diye bir pointer mı var ?

IAP iap_entry


Burada IAP nesne olarak kabul edilip çoğaltılıyor mu ?

iap_entry =(IAP)IAP_LOCATION;

Anlamadım
iap_enrty(command,result);

fatih6761

typedef void (*IAP) (unsigned long[],unsigned long[]);

Hocam buna "Function Pointer" deniyor. Yani nasıl "int" bir tipse, "void" bir tipse, fonksiyonlar da tip olarak tanımlanabiliyor.
Burada IAP "tipi", dönüş değeri "void" olan, unsigned long[] cinsinden iki parametre alan fonksiyon -aslında tip- anlamına geliyor.
C dili nesne yönelimli bir dil değildir. Dolayısıyla nesne olarak yorumlamaz.
IAP iap_entry;
iap_entry =(IAP)IAP_LOCATION;

Bu kod, bellekte IAP_LOCATION adresinde, parametre olarak iki adet unsigned long[] alan bir fonksiyon olduğu anlamına geliyor ve bu fonksiyonun adresi iap_entry değişkenine atılıyor. IAP'ı da bir tip olarak düşünün.
void foo(void);

nasıl bir fonksiyon belirtiyorsa
IAP iap_entry;

de bir fonksiyon belirtiyor. Kullanılmasının tek sebebi dinamik olarak bellekte herhangi bir adresi taşıyabilmesi.
Bu fonksiyon işaretçileri nerede kullanılır derseniz, en basitinden sıralama algoritmaları kullanır.
void qsort(void *base, size_t nmemb, size_t size,
            int(*compar)(const void *, const void *));

Burada compar parametresi bir değişkendir ve algoritma karşılaştırmayı bu değişkenin işaret ettiği fonksiyona yaptırır.
int compare_values(int *a, int *b)
{
return a > b;
}

int main()
{
qsort(siralanacak_dizi, eleman_boyutu, dizi_boyutu, compare_values);
}

Burada qsort'a karşılaştırmaları yapan fonksiyonumuzun adresi yollanıyor.
Gerçek fonksiyonlar da aslında pointer'larıyla aynı şekilde ele alınır.
Function pointer, bir işaretçi ise işaret ettiği değeri çağırmak için '*' önekini kullanmalısınız. Ancak fonksiyonlar da aynı şekilde ele alındığından;
void my_funcion(int n)
{
printf("n is %d", n);
}

void (*foo)(int);
foo = &my_function;

foo(1);    // doğrudan fonksiyon olarak çağır
(*foo)(2); // işaretçi mantığıyla çağır

iki kullanımda aynı işi yapar ve ikisi de doğrudur.
Dkkat ettiyseniz foo'ya fonksiyonun adresi atanmıştır ('&' karakteri ile). Derleyici, foo(..) ve (*foo)(..) kullanımlarının her ikisini de fonksiyona çağrı olarak yorumlar. İşaretçi olarak bakarsak, foo, void döndüren ve int parametre alan bir fonksiyona işaret eden bir pointer'dır. *foo değeri otomatik olarak void döndüren ve parametre olarak int alan bir fonksiyonun ta kendisidir. Her iki türlü de çağrılır. İşlemci bu satırlarda Program Counter adresini yedekler, işlemciyi foo'nun içeriğine atlatır ve fonksiyon çalışmış olur.
C++ 'ta funcion pointer yerine virtual fonksiyonları kullanmak daha uygundur(diye biliyorum).
Umarım açıklayabilmişimdir. İyi çalışmalar...