2015-10-18 2 views
0

Так что я не могу показаться, чтобы получить этот простой указатель на функцию запуска без SEG вызвавшего отказВызов функции указатель передается в другую функцию

Вот что я работаю с:

test.c:

#include <stdint.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 

typedef void (*lwpfun)(void *);  
static void indentnum(void * num); 

int main(int argc, char *argv[]){ 
    lwp_create((lwpfun)indentnum,(void*)42); 

    return 0; 
} 

static void indentnum(void *num) { 
    printf("Indent num: %d\n", *(int *)num); 
} 

lwp.c

#include "stdio.h" 
#include <stdlib.h> 

void lwp_create(void (*lwpfun)(void *), void *arg){ 
    (*lwpfun)(arg); //Seg faulting 
} 
+1

Назначение литералов указателям почти никогда не является хорошей идеей. – Downvoter

+0

Почему вы накладываете первый аргумент на 'lwp_create()'? Почему все эти броски вообще? –

ответ

0
lwp_create((lwpfun)indentnum,(void*)42); 

Нет необходимости, чтобы бросить, но вы должны взять на себя адрес вашей функции, чтобы сделать это указатель функция (логический, не так ли?)

lwp_create(&indentnum,(void*)42); 

(это будет работать без адреса оператора, это просто для ясности)

Следующая проблема:

static void indentnum(void *num) { 
    printf("Indent num: %d\n", *(int *)num); 
} 

Если вы действительно хотите, чтобы int был отправлен в адрес void *, это не делает его волшебным указателем - так что просто верните его на int ((int) num). разыменования это, конечно, сбой, почему должен 42 быть действительным указателем?

Тогда здесь:

void lwp_create(void (*lwpfun)(void *), void *arg){ 
    (*lwpfun)(arg); //Seg faulting 
} 

Аргумент должен иметь тип lwpfun (? Вы сделали, что typedef по причине, справа) ... Вы можете назвать это так же, как вы вызываете обычную функцию. Так что попробуйте следующее:

void lwp_create(lwpfun callback, void *arg){ 
    callback(arg); 
} 
+0

Это работает как шарм, давая вам принятый ответ. Мучо Грасиас! –

+0

@EmmettHarper, пожалуйста. Я предлагаю вам также рассмотреть другие ответы, потому что они сосредоточены на действительно важной проблеме, с которой вы столкнулись здесь: помните, что приведение указателя 'int' к указателю не универсально переносимо, хотя оно работает на * большинстве * платформ. –

+0

Использование имени функции неявно распадается на указатель; 'indentnum' точно так же, как' & indentnum' (а также '* indentnum' и' ******************* indentnum') –

1

Изменение:

lwp_create((lwpfun)indentnum,(void*)42); 

к:

lwp_create(indentnum, &(int []){42}); // use of a C99 compound literal 

или C89:

int x = 42; 
lwp_create(indentnum, &x); 

Ваша первая форма имеет не передать указатель на объект с int значением 42 но указатель сформированного с преобразованием от 42 до значения указателя.

+0

Это не работает, похоже, работает, но способ, которым я изначально работал, отлично работает. Извините, но я не думаю, что это правильно вообще –

+0

@EmmettHarper было протестировано и отлично работает в моей системе. – ouah

2

Вы передаете num как (void*)42, который является указателем на мусор, затем литье и разыменование его. Либо передайте адрес переменной int, либо (менее переносимо) верните его обратно в int.

Смежные вопросы