2015-06-01 14 views
7
void funcPtr(int a); 

int main(){ 
    int k=1; 
    void (*funcPtr2)(int); 

    funcPtr2 = (void*)(funcPtr); 
    // funcPtr2 = (void(*)(int))(funcPtr); 

    (*funcPtr2)(k); 
    return 0; 
} 

void funcPtr(int a){ 
    printf("%d", a); 
} 

Jaka jest różnica między (void*) a (void(*)(argument type) w funkcji odlewania typu wskaźnika?Jaka jest różnica pomiędzy rzutem (void *) i (void (*) (typ argumentu))?

W rezultacie nie pojawia się ostrzeżenie.

Czy to źle? około (void*) odlewanie typu

+0

'błąd: nieprawidłowa przemiana z 'void *' do 'void (*) (int)'' – user657267

+0

Dlaczego by jeden odlew w pierwszej kolejności. Wskaźnik funkcji i zaadresowana funkcja * dopasowanie *? I częściowo jesteście w porządku; nie ma ostrzeżenia, [jest to błąd typu flat-out] (http://ideone.com/8BpCPx) – WhozCraig

+6

C lub C++? Wybierz jedno_. –

Odpowiedz

7

Is this wrong? about (void*) type casting

Tak, jest.

Standard C nie pozwala na konwersję wskaźnika funkcji na wskaźnik obiektu lub przypisanie między nimi. Jeśli swój poziom ostrzeżeń kompilatora, można uzyskać Ostrzeżenia/błędy, takie jak kompilacja z:

gcc -Wall -Wextra -pedantic-errors -std=c11 file.c 

Nie jestem pewien, dlaczego myślał o odlewania wskaźnik funkcji. Pod warunkiem, że typ wskaźnika funkcja odpowiada funkcji, po prostu przypisać go:

funcPtr2 = funcPtr; 

marginesie:

Można użyć wskaźnik funkcji jak funkcja:

funcPtr2(k); 

i używać standardowy prototyp dla main, taki jak:

int main(void) 
+0

Ograniczenie uniemożliwiające przekształcenie wskaźnika danych kodu <-> pochodzi z czasów modelu pamięci Intel (http://en.wikipedia.org/wiki/Intel_Memory_Model) i prawdopodobnie podobne urządzenia na innych architekturach. Na przykład. w modelu "średnim", 'sizeof (void *) == 2', ale' sizeof (void (*) (void)) == 4', powodując, że konwersje są niebezpieczne. Oczywiście żadna z tych platform i modeli pamięci nie ma żadnego znaczenia dla POSIX. –

0
(void*) 

rzuca wskaźnik na wskaźnik do unieważnienia lub wskaźnik ogólny.

void(*)(int) 

to wskaźnik funkcji do funkcji przyjmującej argument int i zwracającej nic.

int fn(float f) { return f * 3.14; } 

void* ptr = fn; 

Zrobił ptr adres pierwszej instrukcji maszynowej fn ale nie pozwalają, aby go używać.

int(*ptr)(float) = fn; 
// or 
typedef int(FnPtr)(float); 
FnPtr* ptr = fn; 

pobiera adres w taki sposób, że kompilator nie wie, jaki rodzaj wywołania funkcji jest wskazał więc, że można wywołać funkcję

int n = ptr(2.5); 

które mogą być przydatne do robienia czegoś jak

void get_data(int socket, int timeout, void(*callback)(char*, size_t)); 

Którą funkcję mogę przekazać innej funkcji.

void recv_data(char* data, size_t len) 
{ 
    ... 
} 

... 

get_data(socket, 60, recv_data); 
+1

W C, nie można rzutować wskaźnika funkcji na 'void *'. –

+0

@undur_gongor Niektóre kompilatory pozwalają na pewne poziomy ostrzeżeń i robię to na moim podpalaczu, więc zdecydowałem się nie argumentować tej sprawy. – kfsone

+0

(Ale właśnie dlatego wybrałem 'byłoby') – kfsone

1

Jest to problem z dlsym oświadczył void *dlsym(void *restrict handle, const char *restrict name). dlsym zwraca wskaźnik do funkcji o nazwie name zdefiniowanej i dostępnej poprzez handle.
Jednak, jak stwierdza @BlueMoon, nie jest to zdefiniowane w ISO C i gcc istotnie narzeka, jeśli jest pedantyczny. POSIX starał się rozwiązać tę i wymagającą zgodną implementację, aby uczynić tę obsadę dobrze zdefiniowaną w swojej nieokreśloności.

Od POSIX

Note that conversion from a void * pointer to a function pointer as in:

fptr = (int (*)(int))dlsym(handle, "my_function");

is not defined by the ISO C standard. This standard requires this conversion to work correctly on conforming implementations.

Innym sposobem, aby to Conforming odlew jest najpierw przekonwertować wskaźnik funkcji do void** a następnie dereference niego. To powinno być dobrze zdefiniowane. W twoim przypadku,

void funcPtr(int a); /* symbol to extract */ 

int main(void) 
{ 
    void (*fn)(int); 
    *(void**)(&fn) = dlsym(your_handle, "funcPtr"); 


    fn(5); 
} 
Powiązane problemy