2014-11-24 72 views
0

我是C語言的初學者,在JavaScript之後開始並且無法習慣這些類型。C:數據類型。 sqrt函數與int工作爲什麼?

好的math.h的sqrt函數應該與雙打一起工作,據我所知,在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 2014-11-24 13:16:22

+0

你的猜測是正確的。 1)請示例2)您不需要它:http://ideone.com/x3AQqt – mch 2014-11-24 13:19:04

+0

「爲什麼如果我傳遞了錯誤的類型但不包含sqrt,則會出現其他函數出錯」 - 這不是一般事情;一些隱式轉換是可能的,有些則不是。 2.「爲什麼我們需要這個?」 - 什麼導致你相信你需要那個? **你沒有。** – 2014-11-24 13:47:38

回答

1

爲什麼所有這些【二初始化]工作?

第一初始化float b = sqrt(1234)工作,因爲語言「upcasts」的整數文字1234double調用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

謝謝,所以編譯器可以upcast但不能downcast?所以如果我將double傳遞給需要int的函數,我會得到一個錯誤嗎?我想我可以試試這個:) – Mcs 2014-11-24 13:38:20

+0

@Mcs假設函數有一個合適的原型,編譯器會這樣做。 – dasblinkenlight 2014-11-24 13:49:23

0

爲了讓編譯器能夠將正確的參數傳遞給函數,需要知道函數期望的類型。這意味着您必須提供該函數的完整聲明,並且可以通過兩種方式完成。

sqrt()的情況下,您通常會使用#include <math.h>。另一種方法是在您的源代碼中明確聲明函數:double sqrt (double);

一旦編譯器知道函數期望並返回的是什麼類型,它將在可能的情況下將參數轉換爲正確的類型。可以隱式轉換intdouble

如果未能聲明類型的函數的參數的,所述默認參數提升將被應用到的參數,這意味着小的整數類型將被轉換爲int,和float將被轉換爲double。您的int參數將作爲int使用某種特定於實現的方法盲目傳遞,而sqrt()函數將使用其他特定於實現的方法檢索其參數爲double。顯然,如果這兩種方法不同,這將無法正常工作,這就是爲什麼在沒有完整聲明的情況下將錯誤類型傳遞給函數會導致未定義的行爲

在C標準的最後兩個版本中,不允許在沒有事先聲明的情況下調用函數,並且編譯器需要發出診斷消息。但是,由於歷史原因,該聲明不需要提供參數的類型。

相關問題