#include <stdio.h>
int main() {
foo(22.3);
return 0;
}
void foo(int x) {
printf("%d", x);
}
Печатает 1. Почему вместо этого не печатается 22? Я считаю, что когда я вызываю foo без объявления явного прототипа, c генерирует неявный прототип, который преобразует short и char в int, а float в double в аргументах функции. Таким образом, 22.3 не затрагивается при вызове foo(22.3), а затем в вызываемой функции параметру int x присваивается значение 22.3: int x = 22.3
, что приводит к числовому преобразованию, при котором дробная часть отбрасывается, и в x остается только 22. Так почему же он не печатает 22 вместо 1?
Я думаю, что ошибся в том, что происходит, когда вызывающий вызывает вызываемый с несовпадающими типами параметров?
Сделайте себе одолжение: включите предупреждения в своем компиляторе (какой бы широкой категории он ни обладал, например, «все» или «большинство», поэтому -Wmost
или -Wall
в командной строке для Clang или GCC), настройте его на обработку предупреждений как ошибок (-Werror
) и настройте его на использование последней версии стандарта C, который он поддерживает (для GCC или Clang используйте -std=c17
, -std=c11
или -std=c99
). Это отключит использование функций без прототипов и выдаст вам ошибки из-за несоответствия аргументов. Сначала вы можете получить больше ошибок, но в конечном итоге вы будете страдать меньше от горя.
Вы вызываете функцию с параметрами, несовместимыми с аргументами. Поскольку у функции нет прототипа, преобразование double в int не происходит. Это приводит к неопределенному поведению.
Если бы вы передали int
или меньший целочисленный тип, который был бы повышен до int
, то функция работала бы.
Итак, что я получаю из этого, так это то, что когда вы вызываете функцию с аргументами, которые не могут быть неявно преобразованы, чтобы соответствовать параметрам функции, и которые не получают дальнейшего преобразования сгенерированным неявным прототипом ( двойное не будет продвигаться удвоить, потому что он уже удвоился), это приводит к неопределенному поведению? Если бы я вызвал foo('a')
, по правилам неявных преобразований прототипов, аргумент 'a' был бы повышен до int, совместимого с параметрами функции, так что в итоге все заработало бы, я могу предположить.
Вы забыли про прототип функции:
#include <stdio.h>
void foo(int); // <--- here!
int main() {
foo(22.3);
return 0;
}
void foo(int x) {
printf("%d", x);
}
Без этого компилятор, вероятно, берет байты с начала вашего значения с плавающей запятой 22.3 и обрабатывает их как целочисленное значение.
Отвечает ли это на ваш вопрос? Передача float функции с аргументом int (заранее не объявленным)