Как функциональный программист с окрашенной шерстью, мне трудно не пытаться обучать мою любимую парадигму на любом языке, который я использую. При написании некоторых C я нашел, что хотел бы выполнить одну из моих функций, а затем передать частично примененную функцию. После чтения Есть ли способ сделать currying в C? и прислушаться к предупреждениям на http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html#Nested-Functions Я придумал:
#include <stdio.h>
typedef int (*function) (int);
function g (int a) {
int f (int b) {
return a+b;
}
return f;
}
int f1(function f){
return f(1);}
int main () {
printf ("(g(2))(1)=%d\n",f1(g(2)));
}
Работа выполняется так, как ожидалось. Однако моя оригинальная программа работает с double
, поэтому я подумал, что просто изменил соответствующие типы, и все будет в порядке:
#include <stdio.h>
typedef double (*function) (double);
function g (double a) {
double f (double b) {
return a+b;
}
return f;
}
double f1(function f){
return f(1);}
int main () {
printf ("(g(2))(1)=%e\n",f1(g(2)));
}
Это создает такие вещи, как:
bash-3.2$ ./a.out
Segmentation fault: 11
bash-3.2$ ./a.out
Illegal instruction: 4
с выбором ошибки, кажущейся случайной. Кроме того, если какой-либо пример скомпилирован с помощью -O3
, сам компилятор выдает сам Segmentation fault: 11
. Я не получаю никаких предупреждений от gcc в любой момент, и я не могу понять, что происходит. Кто-нибудь знает, почему вторая программа терпит неудачу, а первая нет? Или еще лучше, как исправить второй?
Мой gcc i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
, а ядро Darwin Kernel Version 12.1.0: Tue Aug 14 13:29:55 PDT 2012; root:xnu-2050.9.2~1/RELEASE_X86_64
.
edit: Чтобы быть ясным, я понимаю, что то, что я пытаюсь сделать, глупо. Этот код не будет запускаться на любовнике или NYSE. Я пытаюсь понять больше о том, как работают указатели функций в (GNU) C, и объяснить что-то интересное, что я нашел. Я обещаю никогда не делать ничего подобного в реальном мире.