C11's _Generic
Выбор типа - это «правильный» способ сделать то, что вы хотите. Существуют и другие, зависящие от платформы решения, жесткие.
Если вы используете GCC – вы не говорите так eplicitly, но вы используете расширение GCC в typeof
уже – вы можете использовать ССЗ statement expresions и nested functions создать функцию сравнения для qsort
на месте:
double a[5] = {8.4, 8.1, 9.3, 12.2, 5.2};
qsort(a, 5, sizeof(*a), ({
int cmp(const void *p, const void *q) {
const typeof(a[0]) *pp = p;
const typeof(a[0]) *qq = q;
return (*pp < *qq) ? -1 : (*pp > *qq);
}
cmp;
}));
Это создает функцию и возвращает ее адрес. (Последним выражением составного выражения является его значение. Область локальных переменных - выражение оператора, но вложенная функция не создается в стеке, поэтому ее безопасно возвращать указатель на эту функцию.)
Для примитивных типов, где вы хотите, чтобы отсортировать по операторам сравнения <
и >
, вы можете превратить это в макросе:
#define COMPARE(ARRAY)({ \
int cmp(const void *p, const void *q) { \
const typeof(ARRAY[0]) *pp = p; \
const typeof(ARRAY[0]) *qq = q; \
return (*pp < *qq) ? -1 : (*pp > *qq); \
} \
cmp; \
})
qsort(a, 5, sizeof(*a), COMPARE(a));
или даже:
#define SORT(ARRAY, N) \
qsort(ARRAY, N, sizeof(*ARRAY), COMPARE(ARRAY))
SORT(a, 5);
Это не Стандарт C, поэтому, если вам нужна совместимость между платформами, это не может быть и речи.
Представьте предпроцессорные директивы как немой механизм, который получает свою очередь перед компиляцией, для строковых манипуляций, где строки являются строками вашего кода. –
Существуют способы, но это зависит от того, хотите ли вы, чтобы макрос создавал новый тип, новое имя переменной или ссылался на существующий тип или переменную. – Lundin
Звучит немного как проблема xy. Чего вы пытаетесь достичь? –