C'de Temel Fonksiyonların İşleyişleri

Başlatan FxDev, 10 Mayıs 2011, 23:40:17

Klein

Alıntı yapılan: yamak - 11 Mayıs 2011, 19:56:22
int main(void)
{
  long i=5;
  float y;
  y=*(float*)&i;
  printf("%f",y);
    getch();

arkadaşlar yukarıdaki kodu denemek için şöyle küçük bir program yazdım sonucunu 0.0fakat derleyici sonucu 0.000 olarak verdi nedeni nedir acaba?

Daha önceki mesajımda konuyu tam olarak açıklayamadım sanırım. Sebebi ise  sonucu float olaak değerlendir demiş olmam. Aslında bu tanım tam olarak doğru değil.  Eğer  float ifadesinin sağında  * olmasaydı , tanım doğru olacaktı.  Doğru tanım  float pointer olarak değerlendir olacak. 
Şöyle:

eğer  :
y= *(float) &i   demiş olsaydık:
i şaretçisinin gösterdiği adresteki değeri  , float olarak y değişkenine atacaktık.  burada derleyici bir tip dönüşümü işlemi uygulayacaktı. ve sonucu doğru görecektin.
fakat biz dedik ki ,  sonucu float pointer ile gönder.  Bu durumda  sayıyı bir float dönüşüm işlemine tabi tutmadı. Sadece  aldığu 4 baytlık değeri , aynen  y değişkenine aktardı.
Float sayılar  tamsayılar gibi değildir.   tamsayılarda int ve char arasındaki fark sadece  kapladıkları alan farkıdır.
Örneğin: int tipi bir değişkenin içeriği  135 ise  , bu değişkenin ilk baytının içeriği 135 ikinci baytının içeriği ise 0 dır. bu durumda  taşmamak kaydıyla  int veya char tipi değişkenlerin içeriğini birbiri arasında takas edebiliriz.
Ama float sayılarda durum farklı.   Float sayının ilk baytına 135 sayısını yazarsak , float olarak anlamsız bir sayı elde ederiz.

Bu sebeple , yukarıdaki kodda  long sayının içeriğini4 bayt olarak doğrudan  float sayının içine yazdığımız için sonuçta anlamsız bir sayı elde ettik.   bazı printf kütüphaneleri anlamsız float sayıları 0 olarak gösterir. Bu sebeple  0 olarak görmüş olabilirsiniz.

NaMcHo

#16
Alıntı yapılan: Klein - 11 Mayıs 2011, 19:04:37
Alıntı yapılan: NaMcHo - 11 Mayıs 2011, 10:39:39
y  = * ( float * ) &i   şurdaki yapılan işlem nedir?   stm32 nin kütüphanelerindede   *(x *) şeklinde çok tanımlama var burdada görünce dayanamadım sorim dedim.

burada ilk yıldız , i nin gösterdiği adreste bulunan veriyi al ifadesidir. eğer * koymasaydı alacağımız değer  i nin adresi  olacaktı.

float ifadesi Tagli'nin dediği gibi tip dönüşüm ifadesidir. Sonucu float olaak değerlendir demek.  float ifadesinin sağındaki * ise   sonucun da bir pointer ile aktarılacağını ifade ediyor.

Şuda doğru olurmu y pointer olarak tanımlanmış olsa
y=*(float)&i
  ile
y  = * ( float * ) &i
bunlar birbirine denkmidir?2. koddaki y ise float
1.işlemde float pointer olan y ye i'nin adresindeki değeri float olarak gönderiyoruz
2.işlemde ise i'nin adresi içindeki değeri float pointer olarak  float y değişkenine gönderiyoruz

2. yazdığımdan pek bişey anlayamadım şuanda :)

Klein

Yok ikisi aynı ifade değil.  Bir önceki mesajda farkı açıkladım.  Sorun ilk açıklamadaki eksik bir ifadeden kaynaklanıyor.

yamak

Alıntı YapDaha önceki mesajımda konuyu tam olarak açıklayamadım sanırım. Sebebi ise  sonucu float olaak değerlendir demiş olmam. Aslında bu tanım tam olarak doğru değil.  Eğer  float ifadesinin sağında  * olmasaydı , tanım doğru olacaktı.  Doğru tanım  float pointer olarak değerlendir olacak. 
Şöyle:

eğer  :
y= *(float) &i   demiş olsaydık:
i şaretçisinin gösterdiği adresteki değeri  , float olarak y değişkenine atacaktık.  burada derleyici bir tip dönüşümü işlemi uygulayacaktı. ve sonucu doğru görecektin.
fakat biz dedik ki ,  sonucu float pointer ile gönder.  Bu durumda  sayıyı bir float dönüşüm işlemine tabi tutmadı. Sadece  aldığu 4 baytlık değeri , aynen  y değişkenine aktardı.
Float sayılar  tamsayılar gibi değildir.   tamsayılarda int ve char arasındaki fark sadece  kapladıkları alan farkıdır.
Örneğin: int tipi bir değişkenin içeriği  135 ise  , bu değişkenin ilk baytının içeriği 135 ikinci baytının içeriği ise 0 dır. bu durumda  taşmamak kaydıyla  int veya char tipi değişkenlerin içeriğini birbiri arasında takas edebiliriz.
Ama float sayılarda durum farklı.   Float sayının ilk baytına 135 sayısını yazarsak , float olarak anlamsız bir sayı elde ederiz.

Bu sebeple , yukarıdaki kodda  long sayının içeriğini4 bayt olarak doğrudan  float sayının içine yazdığımız için sonuçta anlamsız bir sayı elde ettik.   bazı printf kütüphaneleri anlamsız float sayıları 0 olarak gösterir. Bu sebeple  0 olarak görmüş olabilirsiniz.
Burada *(float)&i yapasaydık doğru olurdu demiştiniz.Fakat ifadenin şu şekilde olması gerekmez mi "(float)*&i"? Zaten dediğiniz gibi yaptığımda derleyici hata veriyo.

Klein

c esnek bir dil.  çoğu zaman  dizilim sonucun değişmesine neden olmuyorsa dizilime çok bakmaz.
örneğin  const char x ile  char const x arasında bir fark yok.
veya  aşağıdaki 3 tanım da birbirinin aynı.
void abc(char unsigned *const _far c ){
}

void abc(char unsigned  const *_far c ){
}

void abc(char unsigned  const _far *c ){
}

çoğu derleyici de buna hata vermez.

bu yüzden  bu dizilime hata verip vermeyeceğini kontrol etmedim. Hata vereceğini de düşünmemiştim açıkçası.  Sonuçta orada önemi olan  float pointere aktarma ile floata çevirip aktarma arasındaki farkı anlatmak olduğu için  çok önesemedim yıldızın nerede olduğunu.

Sonuç olarak mesele şu: 
Eğer *(tip*) &değişken  şeklinde bir dizilim olursa , bu  tip dönüşümü yapmadan verilen tipte bir pointer kullanarak içeriği verir.
eğer  (tip) *&değişken  şeklinde kullanılırsa  tip dönüşümü yaparak verir.