App下載

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

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

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

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

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

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

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

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

運(yùn)行結(jié)果:2.500000。

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

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

首先第一個(gè)問題,這是因?yàn)槿绻ㄌ?hào)起來,那么首先計(jì)算的是 a/b,仍舊是兩個(gè)整數(shù)相除,結(jié)果還是 2,然后經(jīng)過 double 轉(zhuǎn)換,運(yùn)行的結(jié)果就和上面的一樣,都是2.000000。

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

注:unsigned 即 unsigned int。
當(dāng)然,你不嫌麻煩,也可以一個(gè)個(gè)進(jìn)行強(qiáng)制轉(zhuǎn)后再進(jìn)行運(yùn)算。
那么強(qiáng)制轉(zhuǎn)換就一定安全嗎?
如果你老板不知道邀請的這位客人,因?yàn)槌岳钡某阅伭?,突然想要換個(gè)口味,吃個(gè)魯菜。那你都執(zhí)行下去了,結(jié)果很有可能就是項(xiàng)目黃了。
所以,強(qiáng)制轉(zhuǎn)換也不是絕對安全的。程序員在進(jìn)行強(qiáng)制轉(zhuǎn)換的時(shí)候,一定要時(shí)刻保持警惕,要問自己進(jìn)行轉(zhuǎn)換后數(shù)據(jù)會(huì)不會(huì)發(fā)生丟失,是否可能存在非方訪問,如果可以回答這兩個(gè)問題,并且能控制所有可能會(huì)發(fā)生的情況,就可以大膽嘗試去進(jìn)行強(qiáng)制轉(zhuǎn)換。
類型轉(zhuǎn)換是臨時(shí)的
無論是自動(dòng)轉(zhuǎn)換,還是強(qiáng)制轉(zhuǎn)換,目的都是為了本次運(yùn)算而進(jìn)行的一次臨時(shí)變換。轉(zhuǎn)換的結(jié)果是臨時(shí)保存在內(nèi)存中的,而并不會(huì)改變原本的值。
來看一個(gè)例子:
#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;
}

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

代碼中,double 類型的 a 變量通過強(qiáng)制轉(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)容就講到了這里。文章中可能會(huì)存在一些缺漏的知識(shí)點(diǎn),大家如果有什么想法或者疑惑可以在評(píng)論區(qū)留言,一起交流學(xué)習(xí)。最后,感謝大家的觀看!



C

0 人點(diǎn)贊