C資料型別相關問題

2021-07-25 04:10:12 字數 3863 閱讀 8175

位元組數

char 1

short 2

int 由平台(編譯器)決定,可能是2或4,通過sizeof獲知

long 由平台(編譯器)決定,可能是4或8

float 4

double 8

char*/float* /… x86,4位元組,x64,8位元組

資料範圍

(signed)char (1位元組) -128——127

unsigned char 0——255

(signed) short (2位元組) -32768——32767

unsigned short 0——65535

(signed ) int (4位元組) -2147483648——2147483647

unsigned int 0——4294967295

(signed) long(8位元組) -9.223372036854776e+018——9.223372036854776e+018

注:9,223,372,036,854,775,808

unsigend long 0——1.844674407370955e+19

注:18,446,744,073,709,551,615

float -3.4e-38——3.4e+38

double -1.7e-308——1.7e+308

平台無關的整型型別

原因:由於在32位機器和64位機器中,long佔據不同的位元組數;不同編譯器下,int、long都可能占用不同位元組數;為了**的直觀

標頭檔案:stdint.h

int8_t

uint8_t

int16_t

uint16_t

int32_t

uint32_t

int64_t

uint64_t

標頭檔案:stddef.h

ssize_t和size_t分別是sign size_t和unsigned signed size of computerwordsize。它們也是表示計算機的字長,在32位機器上是4位元組,在64位機器上8位元組

浮點數精確至小數點後多少位

檢視float.h的巨集定義

#define flt_dig         6                       

/* # of decimal digits of precision */

#define dbl_dig 15

/* # of decimal digits of precision */

原理是根據浮點數的表示方法,尾數部分就是決定了浮點數的精度,對於float, log10(223) = 6.9237,所以是小數點後6位,對於double,log10(252)=15.6536,所以是小數點後15位

浮點數的整數範圍

ieee754 單精度和雙精度浮點數,能夠精確表示的整數的範圍為

single precision [-2^24, 224],等價於10進製的log10(224)=7.2數量級

double precision [-2^53, 253],等價於10進製的log10(224)=15.9數量級

原理參考

注:受限於浮點數的尾數字,其表示精度是有限的(有效數字),對於很小的小數、或者很大的整數,其精度都會不足。浮點數的精度不是平均分布的呢,和整數的均布不同,浮點數精度是「兩頭差,中間好」。

為什麼對於很小的小數或者很大的整數,會出現精度不足的問題?

這裡需要理解浮點數的表示方法以及浮點數的規範化。

浮點數會將實際的數值規範化為科學計數法的表示形式,如121.75,規範化後是1.2175e+2,當然,計算機裡要換成二進位制的:

(121.75)10 = (1111001.11)2

對二進位制數規範化,1111001.11小數點左移6位,然後乘上2的6次方

浮點數分為符號、指數和尾數三部分。

資料型別 符號位 指數字 尾數字

float 31 30~23 22~0

double 63 62~52 51~0

其中,float的指數字是偏移值,相對127偏移的值就是實際的指數值,如,129,指數值為129-127=2,表示2的2次方;同理,double也是偏移值,相對1023偏移。

尾數儲存規範化後的小數部分,規範化後的整數部分恒為1,所以不用特意分配乙個位元儲存這個1。

對於上面的例子,1111001.11在記憶體中的儲存形式如下(假設這是乙個float型別):

首先,符號位是0

接著,規範化後的值 1.11100111,小數部分共8位,需要補足至23位,最終的尾數字是11100111000000000000000

最後,規範化的指數值是6,表示為偏移值 127+6=133,轉換為二進位制10000101,最終的指數字是10000101

所以,1111001.11在記憶體中儲存為0, 10000101, 11100111000000000000000

回到問題本身,由於浮點數的尾數字有限,有效數字是有限的(float是24位,double是53位),如果實際數值的有效數字超過浮點數字數限制,超出的位將會丟失。

例如,11100111000000010001000.11(十進位制為7569544.75),其有效數字是25位,如果用float表示,即

float value = 7569544.75;
觀察value在記憶體中的值:

0,10010101,11001110000000100010010

0,011111001,0011001100110011001101

將尾數與原始數比較

11100111000000010001000.11

11001110000000100010010

可以發現,尾數部分剛好是原始數小數點左移22位後將高位"1"省略,並且原始數的小數點後第2位被丟棄了,丟棄的同時進行了捨入,如下所示:

……100011 最後一位捨入變成 ……10010

所以最終的value是等於7569544.0的,此時精確到小數點後1位(這裡為0是因為剛才捨入進一了),這種情況就是所謂的「很大的整數」,整數部分的有效數字較多,導致較低位被丟棄。而所謂的「很小的小數」就是指那些無限小數,如0.2,這些無法用二進位制精確表示的小數(因為二進位制是不斷用0.5+0.25+0.125……來逼近原始數的),由於存在尾數捨棄,就會產生精度問題,「很小的小數」就是那些很小的小數字

為什麼float能夠表示的範圍是[-3.4e-38,3.4e+38],而精確表示的範圍是[-2^24, 2^24]?

前者指的是float能夠表示的最大(最小)整數,但是最大整數與第二最大整數之間的差並不是1,也就是說這兩個數之間還存在很多整數float無法表示。

而後者指的就是,在[-2^24, 224]內,最大整數與第二最大整數間的差就是1,即224=16777216,float能夠表示,2^24-1=16777215,float也能夠顯示。

而對於[-3.4e-38,3.4e+38],這裡精確值就不計算了,假設最大值就是 34……56(共39位十進位制數),float能夠表示,但是34……55,float就不能表示了。

原理跟上面乙個問題的是一樣的,都是因為浮點數的尾數字有限,有效數字限制了所能表達的整數值,一旦有效數字大於24,多出來的較低位數字就會被捨棄。

關於printf

注意,printf(或sprintf、scanf、sscanf)的格式化字串 %lf輸出double值,必須加上精確位數,否則預設輸出小數點後6位

資料型別相關

整型常量 十進位制 18 31 long int型常量 123l 123l 123456l 123456l unsigned int型常量 123u 123u 根據實際資料大小確定int型還是long型 l以數字 0 開始的整型常量是八進位制數 022 037 010和10大小不一樣 因為八進位制並...

OCI資料型別與C語言資料型別問題

通過oci函式執行資料庫sql,提取值到記憶體中進行處理,執行sql如下 select out bytes 1024 from bf discharge info t 使用函式ocidefinebypos進行繫結時,oci型別使用的sqlt int,導致資料被取整,應該使用sqlt flt。oci資...

C 資料型別長度問題

一 位元組和字長 位元組,八位就是乙個位元組,是固定概念。字長是指計算機一次能處理的二進位制資料的長度,是乙個非固定的概念。例如,8位計算機的字長為8,即乙個位元組,32位計算機的字長位32,即4個位元組,同理,64位計算機的字長為64,即8位元組。二 c 中的資料型別 1 字元型資料char,該型...