sqrt () - Почему мне разрешено указывать аргумент int, а не только double, и вывод тоже правильный?

Мне интересно, почему компилятор пропустил это и выдает правильный вывод, хотя sqrt() из его прототипа обычно должно получать только значение double в качестве аргумента:

В C99 объявление прототипа:

двойной квадрат (двойной х);

#include <stdio.h>
#include <math.h>

int main (void)
{  
   int i = 9;

   printf("\t Number \t\t Square Root of Number\n\n");

   printf("\t %d \t\t\t %f \n",i, sqrt(i)); 

}

Выход:

 Number      Square Root of Number

 9           3.000000 

Почему компилятор, по крайней мере, не выдает предупреждение, а данный вывод правильный, если я даю функции sqrt() int в качестве аргумента?

Является ли это переходом в Неопределенное Поведение?

Я использую gcc.


Вопрос уже дважды задавался для C++, но не для C, поэтому мой вопрос для C. Я все равно предоставляю ссылки на вопросы для C++:

Почему функция sqrt() отлично работает с переменной типа int, если она не определена для переменной типа int?

Почему sqrt() работает с аргументом int?


person RobertS supports Monica Cellio    schedule 12.12.2019    source источник


Ответы (1)


Это не неопределенное поведение.

Функция определена так, чтобы принимать аргумент типа double. Поскольку тип аргумента известен, вы можете передать int, потому что он может быть неявно преобразован в double. Это то же самое, как если бы вы сделали:

int i = 4;
double d = i;

Правила преобразования аргументов функций изложены в разделе 6.5.2.2p7 Стандарт C относительно оператора вызова функции ():

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

Напротив, если вы передали int в printf, когда строка формата ожидает double, то есть:

printf("%f\n", 4);

Тогда у вас есть неопределенное поведение. Это связано с тем, что типы аргументов неизвестны во время компиляции, поэтому неявное преобразование невозможно.

person dbush    schedule 12.12.2019
comment
Большое тебе спасибо. А также мое желаемое цитирование стандарта. Большое спасибо за ваши усилия. У меня есть еще один вопрос: это также работает с char? Как ф.е. когда я возьму ваш пример: char c = 4; double d = c; или как в моем примере: printf("\t %d \t\t\t %f \n",i, sqrt(c)); Или это относится только к преобразованию из int в double? - person RobertS supports Monica Cellio; 12.12.2019
comment
@RobertS-ReinstateMonica char также можно неявно преобразовать в double. Кроме того, char можно повысить до int в тех местах, где можно использовать int. Это включает в себя аргумент для printf, поэтому вы можете передать значение char со спецификатором формата %d. - person dbush; 12.12.2019