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
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.