Почему предупреждение на C и невозможность компиляции на C++?

StackOverflow https://stackoverflow.com/questions/1642472

Вопрос

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

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

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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

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

Пример кода:

#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)'

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top