Указатель на назначение функции, C - PullRequest
5 голосов
/ 01 сентября 2011

Я не понимаю, почему следующий код генерирует предупреждение:

int func(double a, int b, char c)
{
    return 0;
}
int main()
{
    int(*myPointer)() = func;
    return 0;
}

Я думал, что в C функция с пустым списком параметров означает функцию, которая может получить неизвестное количество параметров. Случается, что func4 получает 3 параметра. Так почему же он несовместим с myPointer?

Это особенно запутанно, потому что следующее компилируется без предупреждения:

void boo()
{
     return;
}
int main()
{
    int(*pointerDude)(double) = boo;
    return 0;
}

Что происходит?

Ответы [ 6 ]

1 голос
/ 01 сентября 2011

Разница между этими двумя случаями объясняется так: если вы передаете параметр функции, которая не принимает ни одного, вы просто занимаете немного памяти в стеке.Если вы не передадите какой-либо параметр в функцию, которая принимает несколько, последняя будет читать случайные данные из стека.

Обновление : изменено на вики сообщества:Добавьте эти исправления из Паскаля Куока:

Приведения указателя функции в обоих направлениях являются законными, информативными предупреждениями от компилятора.Вызов функции с неправильным прототипом является незаконным в обоих случаях.Некоторые ABI требуют, чтобы функция очищала стек, и в этом случае передача параметров функциям, которые не принимают ни одного, повреждает стек так же, как и не передачу параметров функциям, которые их ожидают.

C99 6.3.2.3 пар.8:

Указатель на функцию одного типа может быть преобразован в указатель на функцию другого типа и обратно;результат должен сравниваться равным исходному указателю.Если преобразованный указатель используется для вызова функции, тип которой не совместим с указанным типом, поведение не определено

0 голосов
/ 01 сентября 2011

Я думаю, что проблема связана с приведением параметров, потому что char не 32-битный.Обратите внимание, что если вы измените char на int, это будет работать нормально.Это связано с автоматическим продвижением переменных.

Сравните два:

int func();
int func(double a, int b, int c) 
{
    return 0;
}

и

int func();
int func(double a, int b, char c) 
{
    return 0;
}

gcc выдает предупреждение за секунду, но не запервый

0 голосов
/ 01 сентября 2011

Предупреждение - это просто предупреждение.Честный.

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

0 голосов
/ 01 сентября 2011

В C пустой список параметров означает, что функция не принимает никаких параметров. Я полагаю, вы путаете пустой список параметров с varargs.

Изменение вашего первого примера для включения параметров удалит предупреждение.

int func(double a, int b, char c)
{
    return 0;
}
int main()
{
    int(*myPointer)(double, int, char) = func;
    return 0;
}
0 голосов
/ 01 сентября 2011

Компилятор IIRC C имеет определенные допущения, которые могут привести к очень странным ошибкам, потому что вы не сообщаете ему, сколько стекового пространства ему нужно при вызове этой функции. Тем более, что определения не совпадают, это может позволить кому-то непреднамеренно прочитать объявление указателя на вашу функцию и не принимать никаких параметров, а функция возвращает мусор. Если вы действительно хотите принимать переменные числа параметров, используйте my_func (...) и varargs.

0 голосов
/ 01 сентября 2011

Это предупреждение, которое вы получаете:

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

Вы передаете void, что означает, что потребуется преобразование.Вы должны использовать правильные типы.

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