Почему предупреждение в C и не может компилироваться в C ++? - PullRequest
1 голос
/ 29 октября 2009

Почему этот код

int (*g)(int);
int (*h)(char);
h = g;

В C, при компиляции выдается следующее предупреждение:

'предупреждение: присвоение из несовместимого типа указателя'

В C ++ невозможно компилировать.

Ответы [ 8 ]

6 голосов
/ 29 октября 2009

Прототипы не совпадают. g - указатель на функцию, которая принимает int и возвращает int, тогда как h - указатель на функцию, которая принимает char и возвращает int. Это два отдельных типа и, следовательно, предупреждение (назначение яблок апельсинам).

3 голосов
/ 29 октября 2009

Два указателя функций не имеют одинаковую сигнатуру, поскольку входные параметры различны.

Оба указателя функции возвращают int , в то время как g принимает int в качестве ввода, а h принимает char в качестве входных параметров.

Хотя вы можете иногда смешивать int и char , вы смешиваете указатели функций, поэтому компилятор правильно предупреждает вас о том, что вы можете что-то делать не так.

Пример кода:

#include <stdio.h>

int gf(int n)
{
    return printf("gf(%d)\n", n);
}

int hf(char c)
{
    return printf("hf('%c')\n", c);
}

int main()
{
    int (*g)(int) = gf; // pointer to gf
    int (*h)(char) = hf; // pointer to hf

    g = h; // warning: possibly incompatible functions

    g(65); // cast 65 to char and call h

    return 0;
}

Компиляция:

$ gcc-4.exe -Wall a.c
a.c: In function 'main':
a.c:18: warning: assignment from incompatible pointer type

Запущенная программа:

$ ./a.exe
hf('A')

Как видите, в C это работает хорошо, но компилятор выдает вам соответствующее предупреждение. Если мы попытаемся скомпилировать это как код C ++, компилятор не примет наше жонглирование указателя:

$ g++-4.exe a.c
a.c: In function 'int main()':
a.c:18: error: invalid conversion from 'int (*)(char)' to 'int (*)(int)'
2 голосов
/ 29 октября 2009

Один объявляется как функция, принимающая int, другой - как функция, принимающая char. Это разные подписи, поэтому указатели несовместимы.

1 голос
/ 29 октября 2009

Вы объявили, что g - функция, принимающая один аргумент типа int и возвращающая int, а h - функция, принимающая один аргумент типа char и возвращающая результат int. Сигнатуры двух функций не являются взаимозаменяемыми, поэтому вы не можете присвоить указатель одному указателю другому.

0 голосов
/ 30 августа 2011

Что я могу добавить, так это то, что сопоставление функций в C отличается от C ++. В C вы используете только имя (таким образом, перегрузка параметров невозможна). В C ++ каждая функция имеет свою «сигнатуру», составленную из параметров. (Им пришлось реализовать перегрузку параметров.).

0 голосов
/ 29 октября 2009

Поскольку сигнатуры функций различны, это не является допустимым C или юридическим C ++. Вопрос в том, почему компиляторы относятся к этому по-разному. Ни в одном из стандартов нет большого руководства о том, что делать с программами, которые нарушают стандарт, за исключением того, что для определенных нарушений требуется диагностика (и оба этих случая предоставляют диагностическое сообщение). Стандарты обычно касаются того, что является действительной программой на C или C ++, и что должна делать реализация, когда она предоставляется.

C - значительно более старый язык, чем C ++, и большая часть кода на C была написана на гораздо менее строгих компиляторах, чем сегодня. C ++ был более строгим с самого начала, и поэтому предстандартный код C ++, как правило, является допустимым стандартным кодом C ++, который просто не использует определенные функции.

По этой причине компилятор C более склонен к снисхождению, чем компилятор C ++, предполагая, что компиляторы были написаны для практического использования. В конце концов, есть много кода на C, который беспечно предполагает такие вещи, как эта работа, и кое-что из этого очень полезно, но то же самое нельзя сказать о C ++.

0 голосов
/ 29 октября 2009

Потому что вы назначаете несовместимые указатели. Один указатель на функцию принимает целое число со знаком в качестве аргумента, другой символ (подпись зависит от вашей системы). Хотя оба возвращают одно и то же, они совершенно разные.

Игнорируйте предупреждения, используйте указатели на функции (во время приведения, чтобы он действительно компилировался), и вы поймете, что я имею ввиду:)

0 голосов
/ 29 октября 2009

Вы объявили g и h как функции. На самом деле, мой компилятор выдает ошибку «lvalue Требуется как левый операнд присваивания», и кажется странным, что вы можете получить этот код для компиляции только с предупреждением?

РЕДАКТИРОВАТЬ: Первоначально код в вопросе объявил g и h как функции. Теперь они были изменены на функциональные указатели, которые действительно будут просто предупреждать.

...