2014-11-24 2 views
0

Я новичок в C, начал после JavaScript и не могу привыкнуть к этим типам.C: datatypes. Функция sqrt работает с int почему?

Функция sqrt Okay math.h должна работать с удвоениями и, насколько я понимаю, в C вы не можете передавать неправильные типы в качестве параметров.

Но когда я иду:

int b = sqrt(1234); //it works 

так делает

float b = sqrt(1234); // it works 
int b = sqrt(1234.22) // it works 

Почему все это работает? Как выглядит процесс здесь?

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

Тогда два вопроса?

1) почему я получаю сообщение об ошибке с другими функциями, если я передаю неправильный тип, но не с sqrt? 2) если мы можем просто преобразовать Int плавать как этот

float b = 123.44 
int a = b; 

зачем нам это нужно?

float b = 123.44 
int a = (int) b; 
+0

Когда вы отправляете его как параметр, вы фактически создаете переменную типа параметра, а переданная переменная переходит к типу параметра. – bitcell

+0

Ваша догадка правильная. 1) пример, пожалуйста, 2) он вам не нужен: http://ideone.com/x3AQqt – mch

+0

«Почему я получаю сообщение об ошибке с другими функциями, если я передаю неправильный тип, но не с sqrt» - это не общая вещь; возможны некоторые неявные преобразования, некоторые - нет. 2. «зачем нам это нужно?» - Что заставило вас поверить, что вам это нужно? ** У вас нет. ** –

ответ

1

Почему все эти [два инициализацию] работать?

Первая инициализация float b = sqrt(1234) работает, потому что язык «сбросы» целочисленный литерал 1234 к double перед вызовом sqrt, а затем преобразовать результат в float.

Вторая инициализация int b = sqrt(1234.22) работает по той же причине, но на этот раз компилятор не должен 1234.22 буквальных базового типа перед вызовом, потому что это уже типа double.

Это обсуждается в стандарте C99:

6.3.1.4.1: Когда конечное значение действительного типа с плавающей преобразуется в тип целого числа, отличного _Bool, дробная часть отбрасывается.

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

-

зачем нам это [отливать int a = (int) b;]?

Вы можете вставить отливку для удобочитаемости, но стандарт ее не требует (demo).

+0

спасибо, так что компилятор может взлететь, но не может сбить? поэтому, если я передаю double функции, которая требует int, я получу ошибку? Я думаю, я могу просто попробовать это :) – Mcs

+0

@Mcs Компилятор будет делать это в обоих направлениях, считая, что функция имеет правильный прототип. – dasblinkenlight

0

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

В случае sqrt() вы, как правило, #include <math.h>. Другой способ - явно объявить функцию в исходном коде: double sqrt (double);.

Как только компилятор знает, какие функции ожидаются и возвращаются, он, по возможности, преобразует аргументы в правильные типы. int и double могут быть преобразованы неявно.

Если вы не объявлять типы параметров для функции, продвижение по службе аргумент по умолчанию будут применяться к аргументам, что означает малые целые типы будут преобразованы в int и float будут преобразованы в double. Ваш аргумент int будет слепо передан как int с использованием некоторого метода, специфичного для конкретной реализации, тогда как функция sqrt() будет извлекать свой параметр как double с использованием другого метода, специфичного для реализации. Очевидно, что это не работает должным образом, если эти два метода отличаются друг от друга, поэтому передача неправильных типов функции без полного объявления приводит к неопределенным поведением.

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

Смежные вопросы