Tam Sürümünü Görmek İçin : void *
quasimodo
22/12/2007, 00:42
void bir isaretciye hangi turden adresler atanabilir? Aslinda
standatta soylenen suymus :
"Any pointer may be converted to type void *...''
daha sonra bu
"Any pointer _to an object_ may be converted to type void *...''
http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html
olarak degistirilmis. Ben buradan void bir isaretciye fonksiyon
adresi atanamiyacagini anliyorum? fonksiyon isaretcileri icin
herhangi bir generic isaretci mevcut mu?
acehreli
22/12/2007, 05:44
Fonksiyon isaretcileri icin yok. Nedenini bilmiyorum. :/
Ali
golgepapaz
23/12/2007, 13:58
cunku sizeof(void*) ve sizeof(funcptr) birbirine esit olmayabilir.
acehreli
23/12/2007, 14:08
Tesekkurler ama soru, 'void*'in fonksiyon isaretcileri icin neden kullanilamayacagin degil; neden herhangi fonksiyon isaretcisini tutabilen bir tUrUn olmadigi.
Ali
golgepapaz
23/12/2007, 14:46
yeni keyword koymamak icin heralde. ayrica uye fonksiyonlar icinde bir keyword bulmak gerekecekti buyuk ihtimalle. Zaten gerekte yok, herhangi bir fonksiyon isaretcisini baska bir isaretciye cevirip sonra tekrar eski haline dondurebilirsin .
typedef void (*mygenericfuncptr)();
int foo(int) {return 0;}
int bar(mygenericfuncptr fptr)
{
int(*callee)(int);
callee = reinterpret_cast<int(*)(int)>(fptr)
return callee(5);
}
int main()
{
mygenericfuncptr ptr=reinterperet_cast<mygenericfuncptr>(foo);
bar(ptr);
}
mygenericfuncptr yi kullan kullanabildigin kadar, gerci bu durumda tip guvenligini pencereden disari atmis oluyoruz ama .... :?
acehreli
23/12/2007, 17:29
Cok ilginc! :) reinterpret_cast'in fonksiyon isaretcileriyle de kullanilabilecegini bilmiyordum.
reinterpret_cast C++'la geldigi icin, soru benim icin C'ye kaymis oldu: Neden C'de yok?
Bunun yanitini belki kullanim orneklerine bakarak bulabiliriz. Ornegin pthread_create, 'void*' alan ve 'void*' dOndUren bir fonksiyon alir. Bu sekilde de her tur fonksiyon kullanabiliyoruz. Yapmamiz gereken, aldigimiz parametreleri bir struct'ta toparlamak. DOndUrecegimiz degeri zaten void*'dan gecirebiliyoruz.
golgepapaz'in kullandigi tUrU biraz gelistirirsek, bence iste su tUr yetiyor:
void* (*HerTurFonksiyon)(void*);
Ali
lektroon
23/12/2007, 18:17
acehreli,
void* (*HerTurFonksiyon)(void*);
seklindeki bir fonksiyon isaretcisi ile birden fazla parametre alan fonksiyonlara da isaret edebilir miyiz?
lektroon
23/12/2007, 19:59
evet yeterli oluyormus. denedim ve oldu. ancak golgepapaz'in isaretcisine gore neyi gelistirdik onu anlayamadim ben. her ikisi de ayni sekilde calisiyor.
acehreli
24/12/2007, 03:42
Haklisin, 'void*(*)()' tUrU de oluyor; ama o durumda parametreleri bastan geciremiyoruz. Asagidaki programda 1.2 ve 42 degerlerini, fonksiyon cagrildigi zaman ben uydurdum.
#include <stdio.h>
typedef void * (*HerTurFonksiyon) (void *);
void double_int(double d, int i)
{
printf("%f %d\n", d, i);
}
void double_int_cagiran(HerTurFonksiyon fonk)
{
typedef void (*DoubleIntTuru)(double, int);
DoubleIntTuru double_int_yerel = (DoubleIntTuru)fonk;
double_int_yerel(1.2, 42);
/*
Not: Yukaridaki satirlarin yerine soyle bir acayiplik de
kullanabilirdik :)
((void (*)(double, int))fonk)(1.2, 42);
*/
}
int main()
{
HerTurFonksiyon fonk = (HerTurFonksiyon)double_int;
double_int_cagiran(fonk);
return 0;
}
Eger o degerleri main icindeyken belirlemek isteseydim, bunu 'void*' ile yapmak zorunda kalirdim.
Benim pthread_create ornegi ile gostermek istedigim, lektroon'un sordugu birden fazla parametreyi bir struct icine saklamakti. Yani dogrudan tUr donusumu yapmadan (yoksa zaten gcc sikayet ediyor), bir dOnUsum fonksiyonu ile (asagidaki benim_giris_fonk) isimizi halletmek...
Boyle bir yontem kullanilabildigi icin belki de genel bir fonksiyon isaretcisi tUrUne gerek yok:
#include <stdio.h>
#include <stdlib.h>
/*
Uzerinde konustugumuz ve her tUrlu iste kullanilabilen bir fonksiyon
tUrU.
*/
typedef void * (*HerTurFonksiyon) (void *);
/*
Bu fonksiyon yaptigi islemlerin bir adimini, kendisine verilen bir
fonksiyona yaptiriyor.
O fonksiyonun ne tUrden oldugunu ve ne tUrden parametrelere ihtiyac
duydugunu bilmeden, yine kendisine verilen void* parametreleri ona
gondererek cagiriyor.
Ek olarak, o fonksiyonun urettigi sonucu da kendisine verilen 'sonuclar'
isaretcisi ile kendisini cagirana dOndUrUyor.
*/
void genel_bir_islem_yap(HerTurFonksiyon fonk,
void * parametreler,
void ** sonuclar)
{
printf("genel bir isleme basladim\n");
printf("bir ara adimi bana verilen 'genel' bir fonksiyona yaptiriyorum\n");
*sonuclar = fonk(parametreler);
printf("islemi bitirdim\n");
}
/*
Bizim isimizde kullanilan iki parametreyi bir struct'ta paketledik.
*/
typedef struct
{
double d;
int i;
} DoubleIntParametreler;
/*
Uretilen sonuc degerleri de bir struct'ta paketledik. Burada
DoubleIntParametreler ile ayni tUr oldu ama tamamen farkli tUrler de
uretilebilirdi.
*/
typedef struct
{
double d;
int i;
} BenimSonuclar;
/*
Bizim asIl fonksiyonumuz bu: double ve int alarak o degerlerin iki katini
uretiyor.
*/
BenimSonuclar * benim_asil_fonk(double d, int i)
{
BenimSonuclar * sonuclar = malloc(sizeof(BenimSonuclar));
sonuclar->d = 2 * d;
sonuclar->i = 2 * i;
return sonuclar;
}
/*
HerTurFonksiyon tUrU olarak kullanabildigimiz ve bizim asIl
fonksiyonumuza giris saglayan bir dOnUsum fonksiyonu.
*/
void * benim_giris_fonk(void * void_parametreler)
{
DoubleIntParametreler * parametreler = void_parametreler;
return benim_asil_fonk(parametreler->d, parametreler->i);
}
int main()
{
DoubleIntParametreler parametreler = { 1.2, 42 };
void * void_sonuclar = NULL;
BenimSonuclar * sonuclar = NULL;
genel_bir_islem_yap(benim_giris_fonk, ¶metreler, &void_sonuclar);
/*
Sonuclari isimize yarayan tUre dOnusturuyoruz.
*/
sonuclar = void_sonuclar;
printf("sonuclar: %f ve %d\n", sonuclar->d, sonuclar->i);
free(void_sonuclar);
return 0;
}
Ali
Forum Yazılımı : vBulletin v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.