2016-01-02 2 views
2

Я пытаюсь применить указатель к функции, но я не понимаю используемую технику.Ternary и cast as аргумент qsort

Контекст:

char *lineptr[5000]; 
int strcmp (char *, char *); 
int numcmp (char *, char *);` 

Функция прототипа:

void qsort (void *lineptr[], int left, int right, int (*comp)(void *, void *)); 

Я не понимаю, как работает следующий вызов:

qsort((void**)lineptr ,0 , nlines-1, (int(*)(void*,void*))(numeric?numcmp:strcmp)); 

Конкретно эта часть:

(int (*)(void*, void*))(numeric ? numcmp : strcmp) 

Прототип функции имеет только 4 аргумента, тогда как в вызове функции есть 5 параметров, а пятый - это уравнение. И это компилируется без ошибок.

В один момент я предположил, что он будет назначать либо numcomp или strcmp к функции указателя (*comp) на основе значения numeric. Но я не понимаю, как это будет происходить.

+0

Почему все такие слепки? – alk

+0

Не использовал бы 'int (*) (char *, char *)' вместо 'int (*) (const void *, const void *)' invoke undefined поведение, по крайней мере в момент вызова функции (C11 проект 6.3.2.3/8)? – alk

+0

Здесь нет 'const'. Кастинг 'char *' to 'void *' не вызовет никаких проблем здесь, они оба указателя одинакового размера. И поскольку 'lineptr' является' char'-массивом, qsort будет передавать указатели char на обратный вызов. –

ответ

4

только 4 аргументы передаются, 4-ый аргумент

(int (*)(void*, void*))(numeric ? numcmp : strcmp) 

либо передать указатель на numcmp (если numeric является truthy) или указатель на функцию strcmp (если numeric является falsy).

(int (*)(void*, void*)) просто приведение к сигнатуре функции, чтобы помочь компилятору, потому что компилятор ожидает (int (*)(void*, void*)) как указатель функции (см qsort прототип функции), и вы передаете в указатель на numcmp/strcmp, который (int (*)(char*, char*)).

+0

вы можете поделиться мне ссылкой, где я могу получить подробную || полная 'информация о указателе функции каста' .. ?? –

+0

Вы можете начать [здесь] (http://www.cprogramming.com/tutorial/function-pointers.html) –

+0

...... Спасибо –

2

Есть только 4 аргументы в:

qsort((void**)lineptr,0,nlines-1,(int(*)(void*,void*))(numeric?numcmp:strcmp)); 

Сломанные к одной плате за линию, это выглядит следующим образом:

qsort((void**)lineptr, 
     0, 
     nlines-1, 
     (int(*)(void*,void*))(numeric?numcmp:strcmp)); 

Последняя, ​​кажется, один, который вас в заблуждение. Выражение ?: выбирает одну из двух функций с одинаковым заявленного типа:

numeric?numcmp:strcmp 

Это затем круглые скобки (для старшинства) и приведение к типу указателя функции, которая принимает два void * аргумента:

(int(*)(void*,void*))funcptr 

Тип в операторе литья - это указатель на функцию, которая принимает два аргумента void * и возвращает результат int.

0

Последний аргумент qsort является немного сложным.

qsort((void**)lineptr,0,nlines-1,(int(*)(void*,void*))(numeric?numcmp:strcmp)); 
//        |<--  one argument     --> 

Ценой более развернутого кода, можно упростить эту линию

int(*compare_function)(void*,void*) = (int(*)(void*,void*))numcmp; 
if (!numeric) 
{ 
    compare_function = (int(*)(void*,void*))strcmp; 
} 

qsort((void**)lineptr,0,nlines-1, compare_function);