App下載

從零開始學(xué)習(xí)C語言丨基本數(shù)據(jù)類型的轉(zhuǎn)換

三玹 2022-10-28 17:20:48 瀏覽數(shù) (2175)
反饋
原文: https://mp.weixin.qq.com/s?__biz=Mzg3OTc3MjcyOQ==&mid=2247483760&idx=1&sn=09f4f3240749745231d2642d1dd74035&chksm=cf7e1426f8099d3025183b8932685660102ba9fcf07fd1c48348d0bb8c45ef4a4dd06c328a3a&scene=178&cur_album_id=2588823761982849025#rd

  本文發(fā)布于微信公眾號:三玹

上一篇文章,學(xué)習(xí)了C語言的6種基本數(shù)據(jù)類型。這篇文章就來聊一聊,基本數(shù)據(jù)類型之間的轉(zhuǎn)換。

什么是類型轉(zhuǎn)換?就是將數(shù)據(jù)(變量、數(shù)值、表達式結(jié)果等)從一種類型轉(zhuǎn)換到另一種類型。但這種改變并不是發(fā)生在原本數(shù)據(jù)上,一般都是創(chuàng)建一個新的類型變量來承載轉(zhuǎn)換類型的數(shù)據(jù)。
為什么在程序中需要進行類型改變呢?來舉一個小小的栗子:
在現(xiàn)實生活中,我們現(xiàn)在有一群人的成績(數(shù)值為整數(shù)),我們需要計算他們的平均數(shù)。實際情況中,整數(shù)相除有可能是整數(shù),也有可能是小數(shù)。
但是在C語言當(dāng)中,兩個整數(shù)相除,結(jié)果依然是整數(shù)。但如果實際結(jié)果是有小數(shù)部分的,那這樣的數(shù)據(jù)就失真了,因此就需要用到了類型轉(zhuǎn)換。
來看一段計算代碼:
#include<stdio.h>
int main(){
    int a = 5;
    int b = 2;
    double c = a / b;
    printf("%f", c);
    return 0;
}
運行出來的結(jié)果是:2.000000.
但實際上,這個運行結(jié)果并不是我們想要的。我們都知道 5 除以 2 是等于 2.5,為什么這里卻變成了2.000000呢?
這就是前面提到的,在C語言程序當(dāng)中,兩個整數(shù)相除,結(jié)果還是整數(shù)。5 除以 2 雖然是等于 2.5,但是由于結(jié)果只能是整數(shù),所以丟棄了小數(shù)部分。
但是為什么,還會有小數(shù)點呢?這里就涉及到了類型轉(zhuǎn)換的知識了。
類型轉(zhuǎn)換,一共有兩種形式,一種是自動轉(zhuǎn)換,也叫作隱式轉(zhuǎn)換;另一種是強制轉(zhuǎn)換,也叫作顯式轉(zhuǎn)換。
自動轉(zhuǎn)換
是編譯根據(jù)代碼上下文環(huán)境自行判斷的結(jié)果。
這種轉(zhuǎn)換方式,是系統(tǒng)自己默默地執(zhí)行,是暗地里的,所以也叫作隱式。就像老板讓你去訂一家飯館,但沒有告訴你細(xì)節(jié)問題。那能怎么辦?就只能根據(jù)以往的經(jīng)驗去訂魯菜館。但這種憑經(jīng)驗、憑理解,就會存在一個問題,誰知道老板今天請的客人會不會吃得慣這家飯館的菜呢?
所以說,自動轉(zhuǎn)換是一種不安全的轉(zhuǎn)換方式,可能會存在數(shù)據(jù)失真、精度缺失等問題。
就像我們上面的那一段計算代碼,就發(fā)生了數(shù)據(jù)失真的問題了。
那像這種情況應(yīng)該要怎么解決呢?這就要提另一種轉(zhuǎn)換方式,強制轉(zhuǎn)換。
強制轉(zhuǎn)換
是程序員明確提出要進行的類型轉(zhuǎn)換,用特定的代碼格式去指定某一種類型的轉(zhuǎn)換。
同樣是老板讓你去訂飯店,但會跟你說今天請的這個客人他是四川人,從小在湖南長大,無辣不歡,去定一家川菜館或者湘菜館。這樣子目標(biāo)就很明確了,就不會盲目地定一家魯菜館了。
強制轉(zhuǎn)換是有特定的代碼格式來進行轉(zhuǎn)換的:
typename variable = (typename) expression

typename 即數(shù)據(jù)的類型;variable 即變量;expression 可以是具體的值、某個變量、某個表達式等等。

在前面的那段計算代碼中加上對某個 int 類型進行強制轉(zhuǎn)換之后,再來看看結(jié)果是什么樣的:

#include<stdio.h>
int main(){
  int a = 5;
  int b = 2;
  double c = (double)a/b;
  printf("%f", c);
  return 0;
}

運行結(jié)果:2.500000。

OK,符合預(yù)期的結(jié)果了!

看到這里,肯定有人又有疑惑了,為什么不直接把 a/b 括號起來然后進行轉(zhuǎn)換?為什么只轉(zhuǎn)換其中一個,結(jié)果就正確了呢?

首先第一個問題,這是因為如果括號起來,那么首先計算的是 a/b,仍舊是兩個整數(shù)相除,結(jié)果還是 2,然后經(jīng)過 double 轉(zhuǎn)換,運行的結(jié)果就和上面的一樣,都是2.000000。

第二個問題,為什么只轉(zhuǎn)換其中一個。這是因為在C語言中,不同類型的數(shù)據(jù)在進行操作的時候,首先會根據(jù)轉(zhuǎn)換規(guī)則將這兩種不同類型轉(zhuǎn)換為同一種類型。而轉(zhuǎn)換的規(guī)則,是由低級向高級轉(zhuǎn)換,具體如下圖所示:

注:unsigned 即 unsigned int。
當(dāng)然,你不嫌麻煩,也可以一個個進行強制轉(zhuǎn)后再進行運算。
那么強制轉(zhuǎn)換就一定安全嗎?
如果你老板不知道邀請的這位客人,因為吃辣的吃膩了,突然想要換個口味,吃個魯菜。那你都執(zhí)行下去了,結(jié)果很有可能就是項目黃了。
所以,強制轉(zhuǎn)換也不是絕對安全的。程序員在進行強制轉(zhuǎn)換的時候,一定要時刻保持警惕,要問自己進行轉(zhuǎn)換后數(shù)據(jù)會不會發(fā)生丟失,是否可能存在非方訪問,如果可以回答這兩個問題,并且能控制所有可能會發(fā)生的情況,就可以大膽嘗試去進行強制轉(zhuǎn)換。
類型轉(zhuǎn)換是臨時的
無論是自動轉(zhuǎn)換,還是強制轉(zhuǎn)換,目的都是為了本次運算而進行的一次臨時變換。轉(zhuǎn)換的結(jié)果是臨時保存在內(nèi)存中的,而并不會改變原本的值。
來看一個例子:
#include<stdio.h>
int main(){
  double a = 10.55;
  int a_i = (int)a;
  printf("a=%lf, a_i=%d", a, a_i);
  return 0;
}

運行結(jié)果:a=10.550000,a_i=10

代碼中,double 類型的 a 變量通過強制轉(zhuǎn)換的方式將其轉(zhuǎn)換為 int 類型,并將值賦給了 a_i 變量,這種轉(zhuǎn)換并沒有影響到 a 變量本身的值或者類型。

如果 a 變量的值發(fā)生了改變,那么輸出的結(jié)果應(yīng)該是 10.000000。

最后

關(guān)于基本數(shù)據(jù)類型之間的轉(zhuǎn)換內(nèi)容就講到了這里。文章中可能會存在一些缺漏的知識點,大家如果有什么想法或者疑惑可以在評論區(qū)留言,一起交流學(xué)習(xí)。最后,感謝大家的觀看!



C

0 人點贊