C語言基礎知識(一)


編寫簡單的C程序:HelloWorld
1、編寫簡單的C程序HelloWorld
#include<stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}

程序講解:
#include<stdio.h>:標準I/O頭文件,下文中的printf需要使用這個文件
main():主函數,一個程序的入口。一個程序有且只有一個main()函數
int:代表主函數的返回值類型是int型
printf():格式化輸出,將括號內的內容打印到顯示器上,打印字符串需要用雙引號""引上
return 0;:配合主函數類型使用,一般來說返回0的程序表示程序運行成功
2、編譯器GCC:把程序代碼變成可執行程序
1)GCC是GNU C Compiler的縮寫,是開源的C語言編譯器
2)把hello.c變成可執行程序步驟:
⒈gcc hello.c -o hello
-o的作用:生成的產物的名字
⒉如果不加-o和名字,則默認生成a.out文件
gcc hello.c
則生成產物爲a.out
⒊make hello
此時會調用系統默認的Makefile,編譯hello.c生成hello。
等價於gcc hello.c -o hello
執行該程序:
./hello(./a.out)

3)註釋:
註釋是解釋代碼用的文本,是編寫程序代碼的人爲了方便理解代碼所寫的文本。
常見註釋:
行註釋:使用//,註釋一行
塊註釋:使用/**/,註釋一段
被註釋的文本不會被執行
#include<stdio.h>
int main()//這是一個行註釋
{
printf("Hello World!\n");//這是一個行註釋
/*
這是一個塊註釋
printf("Hello Student\n");//這行被註釋了不會執行
*/
//printf("Hello Boys and Girls\n");//這行被註釋了不會執行,去掉行首註釋即可執行
return 0;
}
/**************使用條件編譯快速註釋代碼***********************/
當需要註釋的代碼量較多時,如果使用塊註釋(/**/)則會出現無法配對等情況
此時可以使用以下方法來快速註釋一段代碼:
#if 0
待註釋代碼……
#endif
此時就註釋了一段代碼。
當需要取消這段註釋時,只需將0改成1即可
#if 1
待註釋代碼……
#endif
/**************使用條件編譯快速註釋代碼end********************/
4)C語言從代碼變成可執行程序的步驟:
預處理 -----> 編譯 -----> 彙編 -----> 鏈接
⒈預處理:去掉註釋,加載頭文件,代替宏定義,條件編譯
需要文件:.c文件
生成產物:預處理文件(以.i結尾)
使用方法:gcc hello.c -E -o hello.i
可以使用vim打開預處理文件來查看生成產物
⒉編譯:使用編譯器進行C語言的語法檢查,如果有語法錯誤,報錯,並結束編譯過程;如果沒有語法錯誤,把C的源程序轉變爲彙編代碼
需要文件:.i文件
生成產物:彙編文件(以.s結尾)
使用方法:gcc hello.i -S -o hello.s
可以使用vim打開彙編文件來查看生成產物
⒊彙編:把彙編源文件通過彙編器生成目標文件(二進制機器語言)
需要文件:.s文件
生成產物:機器碼(或稱爲“目標代碼”,以.o結尾)
使用方法:gcc hello.s -c -o hello.o
可以使用vim打開目標代碼文件來查看生成產物(不過只會看到亂碼)
⒋鏈接:把目標文件執行所依賴的所有二進制的其他目標文件及C的庫文件都整合成一個可執行文件的過程
需要文件:.o文件及各種動態庫或靜態庫
生成產物:可執行程序
使用方法:gcc hello.o -o hello

-o:指定生成的產物的名字
-Wall:讓編譯器報告全部錯誤
我們要養成良好習慣,在編譯過程中添加-o指定生成產物名稱,添加-Wall報告所有的error和warning方便我們調試程序。完整的編譯指令如下:
gcc hello.c -o hello -Wall

編譯完成後(無error,無warning),會生成-o之後的文件(如沒有加-o則會生成a.out文件)
執行文件:
./hello(./a.out)

3、C語言的編程規範:
1)命名規範:
⒈在所有命名中,都應使用標準的英文單詞或縮寫。
⒉所有命名都應遵循達意原則,即名稱應含義清晰、明確。
⒊所有命名都不易過長,應控制在規定的最大長度以內,一般不超過32個字節。
2)編碼規範:
⒈在一行代碼內只寫一條語句;
⒉在嵌套的函數塊中使用一個TAB縮進;
⒊每行長度不應超過80個字符;
(如超過,在行尾加\表示換行)
⒋一個函數建議不要超過200行代碼;
⒌程序中結束符號;(分號)前面不要加空格;
⒍爲程序添加適當的註釋;
3)代碼要求:
⒈代碼格式清楚、層次分明;
⒉代碼易於理解、可讀性強;
⒊代碼具有健壯性,且沒有錯誤;

有關於Linux C的編碼規範,我們強烈推薦閱讀linux kernel coding文檔(讀1~8章和12章)
百度linux kernel coding(中文版:百度linux kernel coding cn)

第四部分:標識符,變量與常量
1、標識符
用來標識變量名、符號常量名、函數名、類型名、文件名等的有效字符序列;
1)標識符的命名規則:
⒈標識符只能由字母、數字和下劃線三種字符組成,且第一個字符必須爲字母或下劃線;
⒉C語言中的標識符大小寫敏感;
⒊用戶自定義的標識符不能與關鍵字同名;

2)關鍵字
關鍵字:對編譯器具有特定含義的標識符,是標識符的一個特殊的集合。
C語言有32個關鍵字,且所有的關鍵字都是小寫
/*******************************C語言關鍵字*****************************************/
1、基本數據類型
void:聲明函數無返回值或無參數,聲明無類型指針,顯示丟棄運算結果。(C89標準新增)
char:字符型類型數據,屬於整型數據的一種。(K&R時期引入)
int:整型數據,表示範圍通常爲編譯器指定的內存字節長。(K&R時期引入)
float:單精度浮點型數據,屬於浮點數據的一種。(K&R時期引入)
double:雙精度浮點型數據,屬於浮點數據的一種。(K&R時期引入)
//_Bool:布爾型(C99標準新增)
//_Complex:複數的基本類型(C99標準新增)
//_Imaginary:虛數,與複數基本類型相似,沒有實部的純虛數(C99標準新增)
//_Generic:提供重載的接口入口(C11標準新增)
2、類型修飾關鍵字
short:修飾int,短整型數據,可省略被修飾的int。(K&R時期引入)
long:修飾int,長整型數據,可省略被修飾的int。(K&R時期引入)
//long long:修飾int,超長整型數據,可省略被修飾的int。(C99標準新增)
signed:修飾整型數據,有符號數據類型。(C89標準新增)
unsigned:修飾整型數據,無符號數據類型。(K&R時期引入)
//restrict:用於限定和約束指針,並表明指針是訪問一個數據對象的唯一且初始的方式。(C99標準新增)
3、複雜類型關鍵字
struct:結構體聲明。(K&R時期引入)
union:聯合體聲明。(K&R時期引入)
enum:枚舉聲明。(C89標準新增)
typedef:聲明類型別名。(K&R時期引入)
sizeof:得到特定類型或特定類型變量的大小。(K&R時期引入)
//inline:內聯函數用於取代宏定義,會在任何調用它的地方展開。(C99標準新增)
4、存儲級別關鍵字
auto:指定爲自動變量,由編譯器自動分配及釋放。通常在棧上分配。與static相反。當變量未指定時默認爲auto。(K&R時期引入)
static:指定爲靜態變量,分配在靜態變量區,修飾函數時,指定函數作用域爲文件內部。(K&R時期引入)
register:指定爲寄存器變量,建議編譯器將變量存儲到寄存器中使用,也可以修飾函數形參,建議編譯器通過寄存器而不是堆棧傳遞參數。(K&R時期引入)
extern:指定對應變量爲外部變量,即標示變量或者函數的定義在別的文件中,提示編譯器遇到此變量和函數時在其他模塊中尋找其定義。(K&R時期引入)
const:指定變量不可被當前線程改變(但有可能被系統或其他線程改變)。(C89標準新增)
volatile:指定變量的值有可能會被系統或其他線程改變,強制編譯器每次從內存中取得該變量的值,阻止編譯器把該變量優化成寄存器變量。(C89標準新增)
5、流程控制關鍵字
1)跳轉結構
return:用在函數體中,返回特定值(如果是void類型,則不返回函數值)。(K&R時期引入)
continue:結束當前循環,開始下一輪循環。(K&R時期引入)
break:跳出當前循環或switch結構。(K&R時期引入)
goto:無條件跳轉語句。(K&R時期引入)
2)分支結構
if:條件語句,後面不需要放分號。(K&R時期引入)
else:條件語句否定分支(必須與if連用)。(K&R時期引入)
switch:開關語句(多重分支語句)。(K&R時期引入)
case:開關語句中的分支標記,與switch連用。(K&R時期引入)
default:開關語句中的“其他”分支,可選。(K&R時期引入)
for:循環(K&R時期引入)
while:循環(K&R時期引入)
/*******************************C語言關鍵字end**************************************/
2、變量
1)變量的類型:
常見的變量類型有:
int:整型,保存整數
char:字符型,保存一個字符(字母、數字、其他符號等)
float:浮點型,保存小數
double:雙精度浮點型,保存小數範圍更大,小數點後位數更多(更精確)
2)變量的定義:
變量必須先定義,再使用
定義一個int型變量:
int a;//定義一個int型變量
定義一個char型變量:
char c;//定義一個char型變量
注意:定義變量不要重名,而且在選擇變量名和其它標識符時,應注意做到“見名知意”,即選有含意的英文單詞(或其縮寫)作標識符。

3)變量的賦值
a = 10;//給int型變量賦值需要整數
c = 'A';//給char型變量賦值需要字符
有時爲了書寫簡便,可以直接在定義變量時賦值。
int a = 10;
char c = 'A';
這種在定義時就直接賦值的使用方法稱爲“初始化”。
變量之間也可賦值,如:
int a = 10;
int b;
b = a;//將a中存放的值(10)賦值給b
4)打印變量的值
使用printf()來打印變量的值。
要打印a中的值10:printf("%d\n",a);
%d代表十進制輸出一個整數。程序運行到這裏,printf函數會掃描逗號後面的內容,遇到第一個變量後將這個變量的值放進%d的位置然後輸出。
練習:交換杯子裏的液體
有兩個杯子(用int型代替),其中一個裝酒,其中一個裝水。如何讓兩個杯子中的液體交換?
提示:需要第三個杯子
答案:
#include<stdio.h>
int main()
{
int a,b,tmp;//3個杯子,tmp用於中間交換用的空杯子
a = 1;//用1代表酒
b = 2;//用2代表水
tmp = a;
a = b;
b = tmp;
printf("a is %d\n",a);
printf("b is %d\n",b);
return 0;
}

3、常量
1)常量:在程序執行過程中,其值不被改變的量
直接常量:直接引用的數字等;
符號常量:使用標識符來代替一個數字(常見的:宏定義常量 和 常變量)
2)宏定義:又稱爲宏代換,是定義一個標識符來代表一個值或一個表達式
使用方法:在程序開頭使用,#define
#define MAX 10
定義一個宏定義,使用MAX來代替10
練習1:
使用宏定義PI來定義3.1415926,計算圓的面積
答案:
#include<stdio.h>
#define PI 3.1415926
int main()
{
float r,area;
r = 5.0;
area = PI*r*r;
printf("%f\n",area);
return 0;
}
練習2:租船問題。
寫程序計算遊客需要付的租船的費用。租船每小時30元,押金100元。遊客輸入租船時間,計算出租船費用。租船費用=時間*每小時錢數+押金。
要求押金與每小時錢數使用宏定義。
答案:
#include<stdio.h>
#define YAJIN 100
#define PERHOUR 30
int main()
{
int hour;
printf("請您輸入需要租船的時間:");
scanf("%d",&hour);
printf("需要支付:%d元\n",hour*PERHOUR+YAJIN);
return 0;
}
宏定義的使用階段:在預處理階段,將所有的宏換成宏值
宏定義也可定義表達式:
#define ADD(a,b) (a)+(b)
#define MUL(a,b) (a)*(b)
注意:如果要使用宏定義來代替表達式,需要在每個表達式的變量都加上括號以防止出現計算錯誤
練習:輸入程序,對比以下兩個宏定義的不同,思考產生不同結果的原因。
#include<stdio.h>
#define FUN1(a,b) a * b
#define FUN2(a,b) (a)*(b)
int main()
{
int a=2;
int b=3;
printf("%d\n",FUN1(a+b,b+a));
printf("%d\n",FUN2(a+b,b+a));
return 0;
}
執行程序,輸出:
13
25
答案:
FUN1的宏替換會變成:a+b*b+a
FUN2的宏替換會變成:(a+b)*(b+a)
因此兩個宏替換會得到不同的結果。
3)常變量
常變量:變量值不可改變的量,使用const修飾
const int a = 10;//定義一個常變量
注意:
const修飾後的變量會變成只讀,因此無法再次賦值。因此初始化常變量需要在定義時直接賦值。
常變量與宏定義常量的區別:
宏定義常量是在預處理階段,使用宏名來代替宏值。而常變量是在程序運行時,程序在內存分配的一個變量,只不過變量不允許再次賦值。因此宏定義沒有佔用內存,而常變量佔用了內存。
從效率上來說,宏定義的效率高於常變量,因此更加常用
4)常量與後綴:
有時候我們需要顯式地表示出常量的類型,這時候我們可以在常量後加後綴
u或U:unsigned類型,如123u
l或L:long類型,如123l
ll或LL:long long類型,如123456ll
f或F:float類型,如0.123f

第五部分:數據類型與類型轉換
1、C語言的數據類型分類
C語言的數據類型分類:
基本數據類型:
整型int
字符型char
浮點型:
單精度浮點型float
雙精度浮點型double
構造數據類型:
數組(如int a[])
結構體struct
聯合體(或叫共用體)union
枚舉類型enum
指針類型(如int *p)
空類型void
2、int,unsigned int,short,long
1)整型int:
大小:16位2字節 或 32位4字節(取決於編譯器)
存儲格式:0~30位是數據位,第31位是符號位,用0代表正數,1代表負數。負數用補碼存儲。
存儲範圍:-2^31 ~ 2^31-1
打印格式:%d(十進制)、%o(八進制)、%x或%X(十六進制)
如需要打印八進制和十六進制的特殊格式,加#
%#o(打印八進制數,數前有0表示八進制數),%#x(打印十六進制數,數前有0x表示十六進制數)
說明:
int類型用於存放整數,佔16或32位(取決於編譯器),2或4字節。其中第31位爲符號位(符號位0代表正數,1代表負數),後面幾位爲數據位
負數在內存中是以補碼的形式存儲的。
補碼的計算方法:按位取反,末位加1
常見的有十進制,八進制,十六進制三種數字進制。
八進制輸入輸出格式化控制符使用%o或%#o。八進制數以0開頭,如0666
十六進制輸入輸出格式化控制符使用%x或%X或%#x或%#X。十六進制數以0x開頭,如0x12345678
/*********************原碼、反碼與補碼**************************************/
計算機只能存儲二進制數,因此十進制數、八進制數、十六進制數等在內存中都以二進制的形式存儲的。內存中存儲的二進制數分原碼、反碼和補碼3種。
原碼:將一個十進制數直接轉換成二進制數存儲
例如:9----->1001(原) 0xFA----->11111010(原)
反碼:在原碼的基礎上,按位取反
例如:9----->0110(反) 0xFA----->00000101(反)
補碼:在反碼的基礎上,末位+1。注意進位問題。
例如:9----->0111(補) 0xFA----->00000110(補)
負數在內存中是以補碼的形式存儲的。即:負數的二進制存儲就是其正數的補碼
例如:9----->0111(補)-----> -9 0xFA----->00000110(補)-----> -0xFA
練習:求以下數字的原碼、反碼、補碼。(可以使用計算器)
1、15(10進制)
2、0xE3A4(16進制)
思考:爲什麼計算機要使用補碼來存儲負數?
答案:因爲數字0。負數是正數的相反數,因此邏輯上來說使用反碼存儲負數合理。但是,如果使用反碼存儲負數,數字0會出現問題:
+0--->00000000
-0--->11111111
會發現+0與-0是兩個不同的二進制數。但數字0不能夠被刻意劃分成+0和-0(0只能有一個,即+0與-0必須相等)。因此使用反碼存儲負數會出現問題。
而補碼就不會出現+0與-0不同的問題:
+0--->00000000
-0--->11111111+1--->00000000(最高位的1被捨棄)
因此計算機使用補碼來存儲負數。

思考:對一個數取2次補碼會產生什麼結果?
答案:取2次補碼等於自身
例如:9----->0111(補)
0111----->1001(補)----->9
/*********************原碼、反碼與補碼end***********************************/

2)無符號整型unsigned int:
大小:同int型
存儲格式:0~31位都是數據位,無符號位
存儲範圍:0 ~ 2^32-1
打印格式:%u
說明:
與int型基本相同,區別是int型的符號位不再是符號位而也作爲數據位,因此無符號整型數據比整型數據存儲範圍大2倍,不過無法存儲負數
適用於只有正數的情況
unsigned關鍵字不僅僅可以修飾int類型,還可修飾short long char等類型。
注意:unsigned關鍵字修飾的變量無法接收負數。
無符號數的輸入輸出格式控制是%u
3)短整型short:
大小:16位2字節
存儲格式:0~14位爲數據位,第15位爲符號位,用0代表正數,1代表負數
存儲範圍:-32768 ~ 32767
打印格式:%hd
說明:
short類型與int類型類似,只不過是16位,2字節。第15位爲符號位,後面幾位爲數據位
short類型適用於存儲不太大的數據,節省內存空間。
short類型的輸入輸出格式控制是%hd
4)長整型long:
大小:32位4字節
存儲格式:同32位int類型
存儲範圍:同32位int類型
打印格式:%ld
說明:
在過去的16位編譯器中,int型是16位,所以long類型是32位。
不過在現代的32位編譯器中,int型與long類型已無本質區別。
如果需要考慮程序跨平臺移植(如16位編譯器<--->32位編譯器)需要謹慎選擇使用int還是long
3、char類型:
大小:8位1字節
存儲格式:0~6位都爲數據位(128) 或 0~7位都爲數據位(256,擴展後的ASCII表)
存儲範圍:0 ~ 255
打印格式:%c
說明:
char類型也屬於整型數據類型(int、short、long)的一份子,只不過char類型運算時使用ASCII表來確定值。與其他三個整型數據類型不同的是,char類型默認就是unsigned類型,而其他三個則默認是signed類型。
/*********************ASCII表與轉義字符*******************************/
在計算機的編碼中,字符是使用ASCII表進行編碼的。每一個字符都有一個對應的數字,例如:
'A'--->65
'a'--->97
'0'--->48 等
除了常見的數字、字母、符號(如+-*/%等)外,ASCII表還存儲了一些看不見的控制字符,如:
空或'\0'(字符串結束標誌)--->0
空格--->32
任意的ASCII表內字符都可以用'\'+數字(八進制)的方式來表示,有些還可以用'\'+字符來表示,稱之爲轉義字符。轉義字符即在'\'後的字符不代表了它本來的含義。
常見的轉義字符:
\a:蜂鳴器
\b:backspace退格鍵
\n:換行,光標移動至下行行首
\r:光標移動至本行行首
\f:換頁
\t:tab水平製表符
\\:輸出\
\':輸出'
\":輸出"
\?:輸出?
\0:NULL字符串結束標誌
/*********************ASCII表與轉義字符end****************************/
4、float與double
/*********************浮點數的存儲***************************/
1)浮點數存儲位劃分
浮點數分爲float類型(32位)和double類型(64位)
其中最高位是符號位,代表整個數的正負
指數部分實際存儲的是移碼E,E=e+127(double型中E=e+1023)。若e爲正代表小數點向左移動了e位,反之e爲負代表小數點向右移動了e位。
尾數部分使用科學計數法,轉化成1.XXXXXXX的形式(二進制,浮點數的有效數字),但不存1和.
由此我們可以看出,尾數代表了浮點數的精度,指數代表了浮點數的範圍。
2)浮點數存儲方法:
示例1:2.5的浮點數存儲
⒈先將該數字轉化成二進制形式
2.5(十進制)----->10.1(二進制)
⒉移位。移動小數點,使之變成1.XXXXX*2^e的二進制科學計數法的形式
10.1----->1.01*2
⒊捨棄1.,將尾數部分(XXXXX)存數在浮點數的尾數位部分。注意是由高位起存儲。其餘位補0
01000000000000000000000(尾數)
⒋在第二步的移位過程中,小數點向左移動,因此e的值爲+1,獲得移碼E
E=e+127=128
⒌將E轉換成二進制,存儲在指數位部分
128(十進制)----->1000000
⒍最後確定這個數是正數,最高位爲0。
通過以上幾步我們就得到了2.5的浮點數存儲
2.5(十進制)----->0 1000000 01000000000000000000000(float類型)
示例2:125.5的浮點數存儲
⒈先將該數字轉化成二進制形式
125.5(10進制)----->1111101.1(二進制)
⒉移位。移動小數點,使之變成1.XXXXX*2^e的二進制科學計數法的形式
1111101.1----->1.1111011*2^6
⒊捨棄1.,將尾數部分(XXXXX)存數在浮點數的尾數位部分。
11110110000000000000000
⒋在第二步的移位過程中,小數點向左移動,因此e的值爲+6,獲得移碼E
E=e+127=133
⒌將E轉換成二進制,存儲在指數位部分
133(十進制)----->10000101
⒍最後確定這個數是正數,最高位爲0。
通過以上幾步我們就得到了125.5的浮點數存儲
125.5(十進制)----->0 10000101 11110110000000000000000
示例3:0.5的浮點數存儲
⒈先將該數字轉化成二進制形式
0.5(十進制)----->0.1(二進制)
⒉移位。移動小數點,使之變成1.XXXXX*2^e的二進制科學計數法的形式
0.1----->1.0*2^-1
⒊捨棄1.,將尾數部分(XXXXX)存數在浮點數的尾數位部分。
00000000000000000000000
⒋在第二步的移位過程中,小數點向右移動,因此e的值爲-1,獲得移碼E
E=e+127=126
⒌將E轉換成二進制,存儲在指數位部分
126----->01111110
⒍最後確定這個數是正數,最高位爲0。
通過以上幾步我們就得到了0.5的浮點數存儲
0.5(十進制)----->0 01111110 00000000000000000000000

由上文我們可以看出,如果遇到無法完全轉化成浮點數的小數(例如0.3這種沒法完美轉化成二進制數),則浮點數只能存儲這個數的近似值而非實際值。因此,浮點數存儲的小數不是實際值,只能是近似值。因此,若判斷一個浮點數是否等於某數,我們通常不使用==(判等)符號,而是使用判斷這個數是否在某個極小區間內的方法。
例如:判斷某浮點數f是否等於0
if(f==0)//錯誤
if(f<0.0000001 && f>-0.0000001)//正確
/*********************浮點數的存儲end************************/
1)float類型:
單精度浮點型
大小:32位4字節
存儲格式:符號位(1位)+尾數(23位)+指數(8位)
精度:小數部分最多有效7位,實際有效6位(2^23=8388608,所以是7位)
存儲範圍:-1.17E+38 ~ +3.40E+38(即-2^127 ~ 2^127)
打印格式:%f(十進制計數法),%e(指數計數法)
2)double類型:
雙精度浮點型
大小:64位8字節
存儲格式:符號位(1位)+尾數52(位)+指數(11位)
精度:小數部分最多有效16位,實際有效15位(2^52=4503599627370496,所以是16位)
存儲範圍:-2.22E+308 ~ +1.79E+308(即-2^1023 ~ 2^1023)
打印格式:同float類型
注意:double類型是8字節而float類型是4字節,因此double型比float型的數據更加精確,但計算速度會更慢。

思考:若有一個浮點數(float類型或double類型)以%d的方式打印,會出現什麼結果?
示例:
#include<stdio.h>
int main()
{
float a = 2.5;
printf("%d\n",a);
return 0;
}
我們會發現打印的是0。
而將a=2.5改成a=2.3
#include<stdio.h>
int main()
{
float a = 2.3;
printf("%d\n",a);
return 0;
}
我們會發現打印的是一個很大的整數。
這是爲什麼?
答案:由上文我們可以發現,無論float類型還是double類型,打印格式都是%f(或%e),二者的打印格式是一樣的。由此我們可以得出結論,無論float類型還是double類型,printf()函數是一視同仁的。
而float類型是4字節,double類型是8字節。因此爲了方便,編譯器將printf()函數需要處理的數據都轉換成double類型(即float類型數據會轉換成double類型,double類型不變)。
而在實際輸出過程中,printf()函數是根據數據所佔內存大小來讀取數據的,即打印int類型的時候取4字節。
2.5從float類型轉換成double類型後,低32位全部是0。而在打印的時候,printf()函數只取32位(由最低位向前)打印,會取得32個0。因此會打印出整數0。
而2.3因爲無法完全轉換成二進制數,因此在從float類型轉換成double類型後,低32位仍有數據。在打印的時候,printf()取32位後會取得不全是0的一個數,因此會打印出一個很大的數。

3)long double類型:
大小:96位12字節(取決於編譯器,有8字節、10字節、12字節、16字節幾種情況)
存儲格式:未知
精度:不少於double類型
存儲範圍:不少於double類型
打印格式:%lf,%le
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章