В C присваивание указателя функции переменной с соответствующим типом дает «не может преобразовать ... в присваивании» - PullRequest
4 голосов
/ 10 января 2011

Возьмите следующий код C / C ++:

#include <stdlib.h>

int inc(int i) { return i+1; }  // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }

int main() {
  int (*foo(bool))(int);  // foo is &(bool→(int→int))
  foo = baz;
}

Попытка скомпилировать это (gcc или g ++) дает:

$ g++ test.cc
test.cc: In function ‘int main()’:
test.cc:9: error: assignment of function ‘int (* foo(bool))(int)’
test.cc:9: error: cannot convert ‘int (*(bool))(int)’ to ‘int (*(bool))(int)’ in assignment

Проверьте сами: два типа, на которые он претендуетне может конвертировать между точно такими же .Почему тогда он утверждает, что они несовместимы?

EDIT 1 : проблема исчезает при использовании typedef s (как рекомендуется), например:

int main() {
  typedef int (*int2int)(int);
  typedef int2int (*bool2_int2int)(bool);
  bool2_int2int foo;
  foo = baz;
}

РЕДАКТИРОВАТЬ 2 : Компилятор, конечно, был прав.Проблема с моим исходным кодом, как отмечали многие, состоит в том, что foo в main() является объявлением функции, а не указателем функции.Следовательно, ошибка в присваивании заключалась не в конфликтующих типах , а в присвоении функции , что невозможно.Правильный код:

#include <stdlib.h>

int inc(int i) { return i+1; }  // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }

int main() {
  int (*(*foo)(bool))(int);  // foo is &(bool→(int→int))
  foo = &baz;
}

Ответы [ 5 ]

7 голосов
/ 10 января 2011

Код на самом деле неверный.Проблема в том, что эта строка:

int (*foo(bool))(int);  // foo is &(bool→(int→int))

... не означает, что вы думаете, что это значит.Это интерпретируется как объявление функции с именем "foo".Это имеет смысл.Подумайте об этом - если бы вы хотели форвард объявить «baz», вы бы поставили int (*baz(bool))(int);, верно?Кроме того, поскольку baz - это функция, которая возвращает указатель на функцию, а foo - это указатель на функцию, которая возвращает указатель на функцию, разве вы не ожидаете, что синтаксис будет более сложным?

Вы объявили foo какфункция того же типа, что и baz, а не указатель на функция того же типа, что и baz.

В вашем компиляторе сообщение об ошибке first являетсяполезный - он сообщает вам assignment of function, т.е. вы пытались присвоить функции, что является ошибкой.

Я даже не собираюсь пытаться написать правильное решение без typedefs :-) Вот некоторый код, который компилируется, и я думаю, что это правильно, используя typedefs:

#include <stdlib.h>
#include <stdbool.h>

typedef int(*IntReturnsInt)(int);

int inc(int i) { return i+1; } 
IntReturnsInt baz(bool b) { return b ? &abs : &inc; }

int main() {
  IntReturnsInt (*foo)(bool b);
  foo = baz;
}

В этом примереконцепция двойного указателя функции немного яснее - IntReturnsInt - это тип указателя на функцию, а foo - указатель на функцию, которая возвращает IntReturnsInt ... phew: -)

3 голосов
/ 10 января 2011

Это объявление функции.

int (*foo(bool))(int);

Если вы хотите объявить указатель на функцию, вы должны сделать:

int (*(*foo)(bool))(int);
0 голосов
/ 10 января 2011

Вы не можете назначить тип функции (int (*foo(bool))(int);), вам нужно использовать указатель на функцию

int (*(*foo)(bool))(int);
foo = &baz;
0 голосов
/ 10 января 2011

Трудно быть уверенным, но я думаю, что это ближе к цели ОП:

// baz is a function returning a pointer to a function
int (*baz(bool b))(int) { return b ? &abs : &inc; }

int main() {
  // foo is a pointer to a function
  int (*foo)(int) ;
  foo = baz(true); // Now foo is equal to &abs
}
0 голосов
/ 10 января 2011
#include <stdlib.h>
#include <stdbool.h>

int inc(int i) { return i+1; }  // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }

int main() {
  int (*(*foo)(bool))(int);  // foo is &(bool→(int→int))
  foo = baz;
  return 0;
}

Итак, было несколько побочных проблем, омрачающих основную проблему.Ваш "bool" интерпретировался как нетипизированный параметр по умолчанию - int, потому что фактическим встроенным является _Bool, очерченный ранее отсутствующим #include <stdbool.h>.Отсутствие объявления указателя для объекта в стеке мешало его способности соответствовать типу реального объекта функции в статической памяти чуть выше.

Как только я включил <stdbool.h>, ошибка сместилась на «Требуется lvalue» жалоба, потому что было только объявление функции, а не объект-указатель.Приведенный выше код будет компилироваться без предупреждений или ошибок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...