LINUX.ORG.RU
ФорумTalks

Зацените как GNU C умеет


0

0

#include <stdio.h>

typedef int (*adder_t)(int);

adder_t make_adder(int increment)
{
	int adder(int value)
	{
		return value + increment;
	}

	return &adder;
}

int main(void)
{
	adder_t add3 = make_adder(3);

	printf("%d\n", add3(7));

	return 0;
}
anonymous

И потеря переносимости в довесок

anonymous
()

Не так странно, что оно скушало, как то, что ты это наваял.

redgremlin ★★★★★
()

Феерично

anonymous
()

А если дублировать вызов printf, то на втором вызове add3
получаем coredump. Тоже магия ?

anonymous
()

сильно. не хотел бы я в таком дебагером копаться.

devinull ★★
()

Моя машина (linux 2.6.25, i686, gcc 4.2.3), компиляция
без оптимизаций. Имеем следующее: при вызове make_adder
адрес переменной increment сохраняется в регистре %ecx.
И при вызове add3 значение берётся по адресу в этом регистре.
Понятно что сегфолтится это дело при любой активности перед вызовом
add3.

anonymous
()
Ответ на: комментарий от bioreactor

пугать пациентов биореактора перед посещением топки? Да вы, батенька, садист.

amoralyrr ★☆
()
Ответ на: комментарий от anonymoos

> объясните для глупошных, в чем прикол-то?

В том, что красиво, непереносимо, и неправильно (если adder использует не свои локальные переменные, обращаться к нему можно только во время вызова make_adder).

tailgunner ★★★★★
()
Ответ на: комментарий от anonymoos

В приведенном коде продемонстрирована такая, характерная для функциональных языков программирования, вещь, как т.н. замыкание (closure), но реализованная на C. На вики есть соответствующая статья.

rexadecimal
()

эээ а разве определение функций внутри функций не запрещено?

или я что-то путаю?

anonymous
()

Происходит следующее:
в make_adder выделяется место в стеке,
пусть адрес вершины - x, далее значение increment сохраняется
по адресу x, по адресу x + 4 сохраняются 5 байт - машинный код
операции movl (x), %ecx, далее по адресу x + 9 сохраняется машкод
команды jmp на реальный адрес функции adder. А возвращает
make_adder на самом деле значение x + 4.
Так-то.

anonymous
()
Ответ на: комментарий от anonymous

>В GNU C разрешено

ппц, дожил.

спасибо за линк, а то так бы и умер в неведении)

anonymous
()
Ответ на: комментарий от anonymous

но не возвращать адреса вложенных функций, как и адреса локальных переменных.

Капча levels.

anonymous
()

вложенные процедуры зло

anonymous
()

$ gcc main.cpp main.cpp: In function ‘int (* make_adder(int))(int)’: main.cpp:8: ошибка: a function-definition is not allowed here before ‘{’ token main.cpp:12: ошибка: нет декларации ‘adder’ в этой области видимости

$ gcc -v Используются внутренние спецификации. Целевая архитектура: x86_64-unknown-linux-gnu Параметры конфигурации: ../configure --prefix=/usr --enable-shared --enable-languages=c,c++,fortran,objc,obj-c++,treelang --enable-threads=posix --mandir=/usr/share/man --enable-__cxa_atexit --disable-multilib --libdir=/usr/lib --libexecdir=/usr/lib --enable-clocale=gnu --disable-libstdcxx-pch --with-tune=generic Модель многопотоковости: posix gcc версия 4.3.0 (GCC)

anonymous
()
Ответ на: комментарий от devinull

devinull@gigant:~/dev/est$ gcc main.c
main.c:21:9: предупреждение: no newline at end of file
devinull@gigant:~/dev/est$ ./a.out
10

devinull ★★
()
Ответ на: комментарий от tailgunner

>Чтобы не скомпилировалось, вестимо. а, ну да, как же я сразу не сообразил

devinull ★★
()

C:\test>test.exe 14 C:\Dev-Cpp\bin>gcc.exe -v Reading specs from C:/Dev-Cpp/bin/../lib/gcc/mingw32/3.4.2/specs Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable-languages=c,c++,f77,ada,objc,java --disable-win32-registry --disable-shared --enable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-x --enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-synchronization --enable-libstdcxx-debug Thread model: win32 gcc version 3.4.2 (mingw-special)

anonymous
()

[shaman@bondarenko ~]$ gcc -Wall -O3 ./1.c 
[shaman@bondarenko ~]$ ./a.out 
Ошибка сегментирования
[shaman@bondarenko ~]$ gcc -Wall -O2 ./1.c 
[shaman@bondarenko ~]$ ./a.out 
Ошибка сегментирования
[shaman@bondarenko ~]$ gcc -Wall -O1 ./1.c 
[shaman@bondarenko ~]$ ./a.out 
Недопустимая инструкция
[shaman@bondarenko ~]$ gcc -Wall  ./1.c 
[shaman@bondarenko ~]$ ./a.out 
10
[shaman@bondarenko ~]$ 

Shaman007 ★★★★★
()
Ответ на: комментарий от rexadecimal

> В приведенном коде продемонстрирована такая, характерная для функциональных языков программирования, вещь, как т.н. замыкание (closure), но реализованная на C.

Это не замыкание, а вложенная функция. Такие и в паскале есть. Реализуется это тривиально. Замыкание должно захватывать используемые переменные, чего здесь не происходит. в D 1 такие же "замыкания".

Legioner ★★★★★
()
Ответ на: комментарий от Shaman007

> [shaman@bondarenko ~]$ gcc -Wall -O3 ./1.c

Михаил, перелогиньтесь хотя бы под Макскомом.

Gharik
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.