Чтение сложных объявлений типов в C/C++ задача непростая. Нет, все когда-то слышали, что надо идти кажется направо, а потом вроде налево и тем еще что-то про скобки было, но вот такое объявление может поставить в тупик:
int (*(*)())()
В статье
Reading C type declarations приведено подробное описание и наглядные примеры расшифровки таких объявлений. Встречаются они редко, но всегда в самое неподходящее время...
ИМХО самое ужастное, что есть в C - это указатели на функции.
ОтветитьУдалитьДа ничего ужасного в них нет. Просто с ними редко приходится работать и синтаксис у программиста вылетает из головы. Если руку набить, то работать с ними становится легко и приятно.
ОтветитьУдалитьТут определяется указатель на функцию, не принимающую аргументов и возвращающую указатель на функцию, которая возращает int и так же непринимает аргументов.
ОтветитьУдалитьто есть эквивалентно такому коду
ОтветитьУдалитьtypedef int (*foo)();
typedef foo (*bar)();
Я не говорю, что это чрезмерно сложно. Просто это очень некрасиво. В во многих других языках это сделано гораздо красивее.
ОтветитьУдалитьЭ-м-м... А это не указатель на функцию, типы аргументов которой не определены?
ОтветитьУдалитьЭ-м-м... А это не указатель на функцию, типы аргументов которой не определены?
ОтветитьУдалитьНе очень поняла, что значит "типы аргументов не определены". Там две функции, обе без аргументов.
Вообще Nunquam dormio написал правильный тип. По ссылке рассказывается как он получается.
Nunquam dormio пишет...
ОтветитьУдалитьДа ничего ужасного в них нет. Просто с ними редко приходится работать и синтаксис у программиста вылетает из головы. Если руку набить, то работать с ними становится легко и приятно.
Собсвенно мне приходилось писать под платформу, на которой был только C компилятор(причём результат компиляции выполнялся на виртуальной машине). А хотелось с минимальными усилиями перенести туда кучу кода на C++. И для этой платформы я разрабатывал фрэймворк, использующий что-то вроде классов с наследовнием и виртуальными функциями. Вся система была достаточно сильно завязана на указатели на функции. Работать с ними было действительно легко, но почему-то хотелось лучшего.
void не вписан, для C это и будет, что аргументы и их кол-во не определено
ОтветитьУдалитьАнонимусу: сенькс, именно это я и собирался написать.
ОтветитьУдалитьЧтобы было понятнее:
ОтветитьУдалить$ cat > test.c << EOF
> void test(){}
> int main(){
> test(1);
> return 0;
> }
> EOF
$ gcc -o test.exe test.c
$ cat > test1.c << EOF
> void test(void){}
> int main(){
> test(1);
> return 0;
> }
> EOF
$ gcc -o test1.exe test1.c
test1.c: In function `main':
test1.c:3: error: too many arguments to function `test'
Скобки без аргументов или скобки с void означают, что у функции нет аргументов вообще, а не "количество неопределено".
ОтветитьУдалитьНеопределенное количество аргументов это >= 0 (см. printf(const char*,...) у которого параметров может быть >=1).
Все подобные определения можно сделать более удобочитабельными путём последовательного создания нескольких typedef'ов. Но некоторым кажется, что лучше сэкономить пару строк кода, ведь все равно в данной конструкции они для себя разобрались.
ОтветитьУдалитьХм. сабж поста был Reading С (!)type declarations, т.е migmit и иже :) правы, а nixaroid... немножко невнимателен.
ОтветитьУдалить;) sse
...прям как я :-[ прошу прощения у niRaXoid'а
ОтветитьУдалитьАнонимный(15/10/07 11:36), то есть, как я понял, отсутствие аргументов в скобках не эквивалентно (void) для С???
ОтветитьУдалитьВ статье кстати не затрагивали аргументы функции для того, чтобы не загромождать процесс разбора типа. Но абстрактное определение С
int (*(*foo)())()
будет отличатсья от
int (*(*foo)(int))().
А void f(void); эквивалентно void f();
Или я не прав?
Не прав. См. приведённый мною выше пример - void test() вызванный как test(1) компилится (и даже работает), а void test(void) - нет.
ОтветитьУдалитьА какая версия gcc?
ОтветитьУдалитьА что будет для такого кода?
void test(){}
int main(){
test(1,'a');
return 0;
}
Интересно как можно получить доступ к аргументу такой функции как void test();? Через va_list?
ОтветитьУдалить3.4.4, cygwin
ОтветитьУдалитьКомпилится, запускается.
Да, через va_list, видимо.