黑马程序员C语言基础(第四天)数据类型
https://www.bilibili.com/video/BV15W411K7k6?p=65&spm_id_from=pageDriver
文章目錄
- 數(shù)據(jù)類型
- 常量與變量
- 關(guān)鍵字
- 數(shù)據(jù)類型
- 常量
- 變量 (extern關(guān)鍵字)
- 使用示例(宏定義(Macro definition):#define )(常量:const關(guān)鍵字)
- 進(jìn)制
- 二進(jìn)制
- 八進(jìn)制
- 十六進(jìn)制
- C語言如何表示相應(yīng)進(jìn)制數(shù)(八進(jìn)制以0開頭,十六進(jìn)制以0x開頭)(以不同進(jìn)制打印:十進(jìn)制(%d)、八進(jìn)制(%o)、十六進(jìn)制(%x))
- 計(jì)算機(jī)內(nèi)存數(shù)值存儲(chǔ)方式
- 原碼
- 反碼
- 補(bǔ)碼
- 對(duì)二進(jìn)制數(shù)來說,先減1后取反和先取反后加1得到的結(jié)果是一樣的(對(duì)上面代碼的解釋)
- 補(bǔ)碼的意義(對(duì)計(jì)算機(jī)存儲(chǔ)友好:可存儲(chǔ)負(fù)數(shù),也能統(tǒng)一 +0 與 -0 的表達(dá))
- C語言原碼、補(bǔ)碼、反碼示例
- 示例1
- 示例2
- 示例3(當(dāng)為8進(jìn)制或16進(jìn)制表示時(shí),計(jì)算機(jī)看到的和輸出的都是補(bǔ)碼)
- 示例4:自動(dòng)擴(kuò)展位?(沒搞懂什么時(shí)候會(huì)自動(dòng)擴(kuò)展什么時(shí)候不會(huì)。.。。)
- sizeof關(guān)鍵字(不是函數(shù),只是個(gè)運(yùn)算符)(計(jì)算數(shù)據(jù)類型大小)(有時(shí)有坑)
- 整型:int
- 整型變量的定義和輸出 (%d、%o、%x、%X、%u)
- 整型變量的輸入(scanf取地址&)
- short、int、long、long long(短整型 short %hd)
- 有符號(hào)數(shù)和無符號(hào)數(shù)區(qū)別
- 1) 有符號(hào)數(shù)(signed int a = -10; 相當(dāng)于int a = -10;)
- 2) 無符號(hào)數(shù)(當(dāng)有符號(hào)數(shù)的正數(shù)來處理)
- 3) 有符號(hào)和無符號(hào)整型取值范圍
- 邊緣值示例
- 字符型:char(注意加單引號(hào)表示Ascii,其他不加或雙引號(hào)跟其他如int、string用法類似)
- 字符變量的定義和輸出
- 字符變量的輸入 scanf
- ASCII對(duì)照表(略,自己上網(wǎng)查)
- 轉(zhuǎn)義字符 \n \r \b等 ('\123'為8進(jìn)制轉(zhuǎn)義字符,'\x23'為16進(jìn)制轉(zhuǎn)義字符)
- 數(shù)值溢出
- 實(shí)型(浮點(diǎn)型):float、double(能不用則不用,值有時(shí)候不準(zhǔn)確)
- 類型限定符 extern const volatile register
- 字符串格式化輸出和輸入
- 2.9.1 字符串常量
- printf函數(shù)和putchar函數(shù)
- putchar示例(輸出字符,隱藏很深!)
- scanf函數(shù)與getchar函數(shù)
- scanf示例
- 示例1:用scanf取數(shù)字
- 示例2:用scanf取字符(換行符 \n 會(huì)被吃掉)(\n 的ascii碼是10)
- getchar函數(shù)示例(鍵盤輸入時(shí),貌似比scanf好用)
數(shù)據(jù)類型
常量與變量
關(guān)鍵字
數(shù)據(jù)類型
數(shù)據(jù)類型的作用:編譯器預(yù)算對(duì)象(變量)分配的內(nèi)存空間大小。
常量
常量:
- 在程序運(yùn)行過程中,其值不能被改變的量
- 常量一般出現(xiàn)在表達(dá)式或賦值語句中
變量 (extern關(guān)鍵字)
變量:
- 在程序運(yùn)行過程中,其值可以改變
- 變量在使用前必須先定義,定義變量前必須有相應(yīng)的數(shù)據(jù)類型
標(biāo)識(shí)符命名規(guī)則:
- 標(biāo)識(shí)符不能是關(guān)鍵字
- 標(biāo)識(shí)符只能由字母、數(shù)字、下劃線組成
- 第一個(gè)字符必須為字母或下劃線
- 標(biāo)識(shí)符中字母區(qū)分大小寫
變量特點(diǎn):
- 變量在編譯時(shí)為其分配相應(yīng)的內(nèi)存空間
- 可以通過其名字和地址訪問相應(yīng)內(nèi)存
2) 聲明和定義區(qū)別
- 聲明變量不需要建立存儲(chǔ)空間,如:extern int a;
- 定義變量需要建立存儲(chǔ)空間,如:int b;
(聲明:表示有這個(gè)變量;定義:開辟存儲(chǔ)空間)
從廣義的角度來講聲明中包含著定義,即定義是聲明的一個(gè)特例,所以并非所有的聲明都是定義:
- int b 它既是聲明,同時(shí)又是定義
- 對(duì)于 extern b來講它只是聲明不是定義
示例:extern關(guān)鍵字(只聲明不定義,如果賦值就報(bào)錯(cuò))
使用示例(宏定義(Macro definition):#define )(常量:const關(guān)鍵字)
#include <stdio.h> #define MAX 10 //聲明了一個(gè)常量,名字叫MAX,值是10,常量的值一旦初始化不可改int main() {int a; //定義了一個(gè)變量,其類型為int,名字叫aconst int b = 10; //定義一個(gè)const常量,名為叫b,值為10//b = 11; //err,常量的值不能改變//MAX = 100; //err,常量的值不能改變a = MAX;//將abc的值設(shè)置為MAX的值a = 123;printf("%d\n", a); //打印變量a的值return 0; }注意:
同一個(gè){}內(nèi)部,不能出現(xiàn)兩個(gè)同名變量的定義
進(jìn)制
進(jìn)制也就是進(jìn)位制,是人們規(guī)定的一種進(jìn)位方法。 對(duì)于任何一種進(jìn)制—X進(jìn)制,就表示某一位置上的數(shù)運(yùn)算時(shí)是逢X進(jìn)一位。 十進(jìn)制是逢十進(jìn)一,十六進(jìn)制是逢十六進(jìn)一,二進(jìn)制就是逢二進(jìn)一,以此類推,x進(jìn)制就是逢x進(jìn)位。
十進(jìn)制 二進(jìn)制 八進(jìn)制 十六進(jìn)制 0 0 0 0 1 1 1 1 2 10 2 2 3 11 3 3 4 100 4 4 5 101 5 5 6 110 6 6 7 111 7 7 8 1000 10 8 9 1001 11 9 10 1010 12 A 11 1011 13 B 12 1100 14 C 13 1101 15 D 14 1110 16 E 15 1111 17 F 16 10000 20 10二進(jìn)制
二進(jìn)制是計(jì)算技術(shù)中廣泛采用的一種數(shù)制。二進(jìn)制數(shù)據(jù)是用0和1兩個(gè)數(shù)碼來表示的數(shù)。它的基數(shù)為2,進(jìn)位規(guī)則是“逢二進(jìn)一”,借位規(guī)則是“借一當(dāng)二”。
當(dāng)前的計(jì)算機(jī)系統(tǒng)使用的基本上是二進(jìn)制系統(tǒng),數(shù)據(jù)在計(jì)算機(jī)中主要是以補(bǔ)碼的形式存儲(chǔ)的。
術(shù)語 含義 bit(比特) 一個(gè)二進(jìn)制代表一位,一個(gè)位只能表示0或1兩種狀態(tài)。數(shù)據(jù)傳輸是習(xí)慣以“位”(bit)為單位。 Byte(字節(jié)) 一個(gè)字節(jié)為8個(gè)二進(jìn)制,稱為8位,計(jì)算機(jī)中存儲(chǔ)的最小單位是字節(jié)。數(shù)據(jù)存儲(chǔ)是習(xí)慣以“字節(jié)”(Byte)為單位。 WORD(雙字節(jié)) 2個(gè)字節(jié),16位 DWORD 兩個(gè)WORD,4個(gè)字節(jié),32位 1b 1bit,1位 1B 1Byte,1字節(jié),8位 1k,1K 1024 1M(1兆) 1024k, 1024*1024 1G 1024M 1T 1024G 1Kb(千位) 1024bit,1024位 1KB(千字節(jié)) 1024Byte,1024字節(jié) 1Mb(兆位) 1024Kb = 1024 * 1024bit 1MB(兆字節(jié)) 1024KB = 1024 * 1024Byte十進(jìn)制轉(zhuǎn)化二進(jìn)制的方法:用十進(jìn)制數(shù)除以2,分別取余數(shù)和商數(shù),商數(shù)為0的時(shí)候,將余數(shù)倒著數(shù)就是轉(zhuǎn)化后的結(jié)果。
十進(jìn)制的小數(shù)轉(zhuǎn)換成二進(jìn)制:小數(shù)部分和2相乘,取整數(shù),不足1取0,每次相乘都是小數(shù)部分,順序看取整后的數(shù)就是轉(zhuǎn)化后的結(jié)果。
八進(jìn)制
八進(jìn)制,Octal,縮寫OCT或O,一種以8為基數(shù)的計(jì)數(shù)法,采用0,1,2,3,4,5,6,7八個(gè)數(shù)字,逢八進(jìn)1。一些編程語言中常常以數(shù)字0開始表明該數(shù)字是八進(jìn)制。
八進(jìn)制的數(shù)和二進(jìn)制數(shù)可以按位對(duì)應(yīng)(八進(jìn)制一位對(duì)應(yīng)二進(jìn)制三位),因此常應(yīng)用在計(jì)算機(jī)語言中。
十進(jìn)制轉(zhuǎn)化八進(jìn)制的方法:
用十進(jìn)制數(shù)除以8,分別取余數(shù)和商數(shù),商數(shù)為0的時(shí)候,將余數(shù)倒著數(shù)就是轉(zhuǎn)化后的結(jié)果。
十六進(jìn)制
十六進(jìn)制(英文名稱:Hexadecimal),同我們?nèi)粘I钪械谋硎痉ú灰粯?#xff0c;它由0-9,A-F組成,字母不區(qū)分大小寫。與10進(jìn)制的對(duì)應(yīng)關(guān)系是:0-9對(duì)應(yīng)0-9,A-F對(duì)應(yīng)10-15。
十六進(jìn)制的數(shù)和二進(jìn)制數(shù)可以按位對(duì)應(yīng)(十六進(jìn)制一位對(duì)應(yīng)二進(jìn)制四位),因此常應(yīng)用在計(jì)算機(jī)語言中。
十進(jìn)制轉(zhuǎn)化十六進(jìn)制的方法:
用十進(jìn)制數(shù)除以16,分別取余數(shù)和商數(shù),商數(shù)為0的時(shí)候,將余數(shù)倒著數(shù)就是轉(zhuǎn)化后的結(jié)果。
C語言如何表示相應(yīng)進(jìn)制數(shù)(八進(jìn)制以0開頭,十六進(jìn)制以0x開頭)(以不同進(jìn)制打印:十進(jìn)制(%d)、八進(jìn)制(%o)、十六進(jìn)制(%x))
十進(jìn)制 以正常數(shù)字1-9開頭,如123 八進(jìn)制 以數(shù)字0開頭,如0123 十六進(jìn)制 以0x開頭,如0x123 二進(jìn)制 C語言不能直接書寫二進(jìn)制數(shù) #include <stdio.h>int main() {int a = 123; //十進(jìn)制方式賦值int b = 0123; //八進(jìn)制方式賦值, 以數(shù)字0開頭int c = 0xABC; //十六進(jìn)制方式賦值//如果在printf中輸出一個(gè)十進(jìn)制數(shù)那么用%d,八進(jìn)制用%o,十六進(jìn)制是%xprintf("十進(jìn)制:%d\n",a );printf("八進(jìn)制:%o\n", b); //%o,為字母o,不是數(shù)字printf("十六進(jìn)制:%x\n", c);return 0; }計(jì)算機(jī)內(nèi)存數(shù)值存儲(chǔ)方式
原碼
一個(gè)數(shù)的原碼(原始的二進(jìn)制碼)有如下特點(diǎn):
- 高位做為符號(hào)位,0表示正,為1表示負(fù)
- 其它數(shù)值部分就是數(shù)值本身絕對(duì)值的二進(jìn)制數(shù)
- 負(fù)數(shù)的原碼是在其絕對(duì)值的基礎(chǔ)上,最高位變?yōu)?
下面數(shù)值以1字節(jié)的大小描述:
十進(jìn)制數(shù) 原碼 +15 0000 1111 -15 1000 1111 +0 0000 0000 -0 1000 0000原碼表示法簡單易懂,與帶符號(hào)數(shù)本身轉(zhuǎn)換方便,只要符號(hào)還原即可,但當(dāng)兩個(gè)正數(shù)相減或不同符號(hào)數(shù)相加時(shí),必須比較兩個(gè)數(shù)哪個(gè)絕對(duì)值大,才能決定誰減誰,才能確定結(jié)果是正還是負(fù),所以原碼不便于加減運(yùn)算。
反碼
- 對(duì)于正數(shù),反碼與原碼相同
- 對(duì)于負(fù)數(shù),符號(hào)位不變,其它部分取反(1變0,0變1)
反碼運(yùn)算也不方便,通常用來作為求補(bǔ)碼的中間過渡。
補(bǔ)碼
在計(jì)算機(jī)系統(tǒng)中,數(shù)值一律用補(bǔ)碼來存儲(chǔ)。
補(bǔ)碼特點(diǎn):
- 對(duì)于正數(shù),原碼、反碼、補(bǔ)碼相同
- 對(duì)于負(fù)數(shù),其補(bǔ)碼為它的反碼加1
- 補(bǔ)碼符號(hào)位不動(dòng),其他位求反,最后整個(gè)數(shù)加1,得到原碼
對(duì)二進(jìn)制數(shù)來說,先減1后取反和先取反后加1得到的結(jié)果是一樣的(對(duì)上面代碼的解釋)
-15的原碼: 1000 0000 0000 0000 0000 0000 0000 1111 反碼: 1111 1111 1111 1111 1111 1111 1111 0000 補(bǔ)碼: 1111 1111 1111 1111 1111 1111 1111 0001 補(bǔ)碼的十六進(jìn)制表示:f f f f f f f 1補(bǔ)碼的意義(對(duì)計(jì)算機(jī)存儲(chǔ)友好:可存儲(chǔ)負(fù)數(shù),也能統(tǒng)一 +0 與 -0 的表達(dá))
(為什么計(jì)算機(jī)打印8進(jìn)制、十六進(jìn)制的時(shí)候打印的是實(shí)際數(shù)的補(bǔ)碼?因?yàn)槿绻瓟?shù)是負(fù)數(shù)不用補(bǔ)碼不好表示)
示例1:用8位二進(jìn)制數(shù)分別表示+0和-0
十進(jìn)制數(shù) 原碼 +0 0000 0000 -0 1000 0000十進(jìn)制數(shù) 反碼 +0 0000 0000 -0 1111 1111不管以原碼方式存儲(chǔ),還是以反碼方式存儲(chǔ),0也有兩種表示形式。為什么同樣一個(gè)0有兩種不同的表示方法呢?
但是如果以補(bǔ)碼方式存儲(chǔ),補(bǔ)碼統(tǒng)一了零的編碼:
十進(jìn)制數(shù) 補(bǔ)碼 +0 0000 0000 -0 10000 0000由于只用8位描述,最高位1丟棄,變?yōu)?span id="ozvdkddzhkzd" class="token number">0000 0000示例2:計(jì)算9-6的結(jié)果
以原碼方式相加:
結(jié)果為-15,不正確。
以補(bǔ)碼方式相加:
十進(jìn)制數(shù) 補(bǔ)碼 9 0000 1001 -6 1111 1010
最高位的1溢出,剩余8位二進(jìn)制表示的是3,正確。
在計(jì)算機(jī)系統(tǒng)中,數(shù)值一律用補(bǔ)碼來存儲(chǔ),主要原因是:
- 統(tǒng)一了零的編碼
- 將符號(hào)位和其它位統(tǒng)一處理
- 將減法運(yùn)算轉(zhuǎn)變?yōu)榧臃ㄟ\(yùn)算
- 兩個(gè)用補(bǔ)碼表示的數(shù)相加時(shí),如果最高位(符號(hào)位)有進(jìn)位,則進(jìn)位被舍棄
C語言原碼、補(bǔ)碼、反碼示例
示例1
示例2
用int和char結(jié)果沒啥區(qū)別,char占一個(gè)字節(jié),int占4個(gè)字節(jié)(32位64位系統(tǒng)下都是4個(gè)字節(jié))
為什么,參考:c語言中,為什么%o、%d、%x輸出的總是32位,如char占一個(gè)字節(jié),但輸出卻是32位
示例3(當(dāng)為8進(jìn)制或16進(jìn)制表示時(shí),計(jì)算機(jī)看到的和輸出的都是補(bǔ)碼)
這是因?yàn)橛?jì)算機(jī)看到的十六進(jìn)制為補(bǔ)碼形式,在打印十進(jìn)制時(shí),它會(huì)把它轉(zhuǎn)換成原碼打印
但問題是,這里為什么沒有自動(dòng)擴(kuò)展為32位呢?
參考:C語言進(jìn)制轉(zhuǎn)換時(shí)自動(dòng)擴(kuò)展位?(原碼、反碼、補(bǔ)碼)(打印%o、%x時(shí)會(huì)自動(dòng)擴(kuò)展到32位【負(fù)數(shù)先得到其十進(jìn)制真實(shí)數(shù)值,再根據(jù)其真實(shí)數(shù)值得到八進(jìn)制、十進(jìn)制補(bǔ)碼】)
示例4:自動(dòng)擴(kuò)展位?(沒搞懂什么時(shí)候會(huì)自動(dòng)擴(kuò)展什么時(shí)候不會(huì)。.。。)
sizeof關(guān)鍵字(不是函數(shù),只是個(gè)運(yùn)算符)(計(jì)算數(shù)據(jù)類型大小)(有時(shí)有坑)
- sizeof不是函數(shù),所以不需要包含任何頭文件,它的功能是計(jì)算一個(gè)數(shù)據(jù)類型的大小,單位為字節(jié)
- sizeof的返回值為size_t
- size_t類型在32位操作系統(tǒng)下是unsigned int,是一個(gè)無符號(hào)的整數(shù)
注意,上面代碼在64位系統(tǒng)下要用%lu打印才不會(huì)警告(不知為什么)
示例1:
#include <stdio.h>int main() {int a;char aa;printf("b = %lu\n", sizeof(a));printf("bb = %lu\n",sizeof(aa));return 0; }
示例2:
結(jié)果:
示例3:
結(jié)果:
整型:int
整型變量的定義和輸出 (%d、%o、%x、%X、%u)
以下全部為以四字節(jié)打印
打印格式 含義 %d 輸出一個(gè)有符號(hào)的10進(jìn)制int類型 %o(字母o) 輸出8進(jìn)制的int類型 %x 輸出16進(jìn)制的int類型,字母以小寫輸出 %X 輸出16進(jìn)制的int類型,字母以大寫寫輸出 %u 輸出一個(gè)10進(jìn)制的無符號(hào)數(shù) #include <stdio.h>int main() {int a = 123; //定義變量a,以10進(jìn)制方式賦值為123int b = 0567; //定義變量b,以8進(jìn)制方式賦值為0567int c = 0xabc; //定義變量c,以16進(jìn)制方式賦值為0xabcprintf("a = %d\n", a);printf("8進(jìn)制:b = %o\n", b);printf("10進(jìn)制:b = %d\n", b);printf("16進(jìn)制:c = %x\n", c);printf("16進(jìn)制:c = %X\n", c);printf("10進(jìn)制:c = %d\n", c);unsigned int d = 0xffffffff; //定義無符號(hào)int變量d,以16進(jìn)制方式賦值printf("有符號(hào)方式打印:d = %d\n", d);printf("無符號(hào)方式打印:d = %u\n", d);return 0; }結(jié)果:
a = 123 8進(jìn)制:b = 567 10進(jìn)制:b = 375 16進(jìn)制:c = abc 16進(jìn)制:c = ABC 10進(jìn)制:c = 2748 有符號(hào)方式打印:d = -1 無符號(hào)方式打印:d = 4294967295
整型變量的輸入(scanf取地址&)
#include <stdio.h>int main() {int a;printf("請(qǐng)輸入a的值:");//不要加“\n”,不然要按回車才出結(jié)果scanf("%d", &a);printf("a = %d\n", a); //打印a的值return 0; }如果加了\n,就成這樣了:
short、int、long、long long(短整型 short %hd)
數(shù)據(jù)類型 占用空間 short(短整型) 2字節(jié) int(整型) 4字節(jié) long(長整形) Windows為4字節(jié),Linux為4字節(jié)(32位),8字節(jié)(64位) long long(長長整形) 8字節(jié)short 也可寫作 short int,long 也可寫作 long int,long long 也可寫作 long long int
為了系統(tǒng)間兼容,通常不使用long int ,直接用long long int
注意:
- 需要注意的是,整型數(shù)據(jù)在內(nèi)存中占的字節(jié)數(shù)與所選擇的操作系統(tǒng)有關(guān)。雖然 C 語言標(biāo)準(zhǔn)中沒有明確規(guī)定整型數(shù)據(jù)的長度,但 long 類型整數(shù)的長度不能短于 int 類型, short 類型整數(shù)的長度不能短于 int 類型。 int 類型整數(shù)的長度不能短于short 類型
- 當(dāng)一個(gè)小的數(shù)據(jù)類型賦值給一個(gè)大的數(shù)據(jù)類型,不會(huì)出錯(cuò),因?yàn)榫幾g器會(huì)自動(dòng)轉(zhuǎn)化。但當(dāng)一個(gè)大的類型賦值給一個(gè)小的數(shù)據(jù)類型,那么就可能丟失高位。
結(jié)果:
一開始編譯不過,后面改后好了:
有符號(hào)數(shù)和無符號(hào)數(shù)區(qū)別
1) 有符號(hào)數(shù)(signed int a = -10; 相當(dāng)于int a = -10;)
有符號(hào)數(shù)是最高位為符號(hào)位,0代表正數(shù),1代表負(fù)數(shù)。
解析:
原碼: -1089474374 1100 0000 1111 0000 0000 1111 0100 0110 反碼: 1011 1111 0000 1111 1111 0000 1011 1001 補(bǔ)碼: 1011 1111 0000 1111 1111 0000 1011 1010B F 0 F F 0 B A2) 無符號(hào)數(shù)(當(dāng)有符號(hào)數(shù)的正數(shù)來處理)
無符號(hào)數(shù)最高位不是符號(hào)位,而就是數(shù)的一部分,無符號(hào)數(shù)不可能是負(fù)數(shù)。
當(dāng)我們寫程序要處理一個(gè)不可能出現(xiàn)負(fù)值的時(shí)候,一般用無符號(hào)數(shù),這樣可以增大數(shù)的表達(dá)最大值。
示例(無符號(hào)數(shù)按有符號(hào)數(shù)打印,結(jié)果也是有符號(hào)數(shù)):
#include <stdio.h> #include <stdlib.h> int main() {unsigned int a =0x8000007b;printf("a = %u\n", a);printf("a = %d\n", a);printf("a = %d\n", 0x8000007b);return 0; }結(jié)果:
a = 2147483771 a = -2147483525 a = -2147483525分析:printf("a = %d\n", a);是怎么出現(xiàn)這個(gè)結(jié)果的
首先,因?yàn)槭谴蛴?span id="ozvdkddzhkzd" class="token operator">%d,它會(huì)默認(rèn)按有符號(hào)數(shù)打印,將0x8000007b看作負(fù)數(shù)補(bǔ)碼:8 0 0 0 0 0 7 b 1000 0000 0000 0000 0000 0000 0111 1011 反碼: 1000 0000 0000 0000 0000 0000 0111 1010 原碼: 1111 1111 1111 1111 1111 1111 1000 0101 - 7 f f f f f 8 5 -21474835253) 有符號(hào)和無符號(hào)整型取值范圍
數(shù)據(jù)類型 占用空間 取值范圍 short 2字節(jié) -32768 到 32767 (-215 ~ 215-1) int 4字節(jié) -2147483648 到 2147483647 (-231 ~ 231-1) long 4字節(jié) -2147483648 到 2147483647 (-231 ~ 231-1) unsigned short 2字節(jié) 0 到 65535 (0 ~ 216-1) unsigned int 4字節(jié) 0 到 4294967295 (0 ~ 232-1) unsigned long 4字節(jié) 0 到 4294967295 (0 ~ 232-1)邊緣值示例
像這種 short 的 -32768,int 的 -2147483648,char的 -128之類的,被稱為邊緣值,邊緣值最高位位1,后面全是0(其實(shí)是將 -0 的位置給了邊緣值)
計(jì)算器怎么秀逗了,怎么顯示補(bǔ)碼?(特么的還真的顯示的是補(bǔ)碼)
(你傻啊,負(fù)數(shù)當(dāng)然顯示的是補(bǔ)碼啊,難不成顯示。。。)(但是為什么要擴(kuò)展到64位?因?yàn)槟愕南到y(tǒng)是64位)
原碼:(錯(cuò)) -2147483648 1 1000 0000 0000 0000 0000 0000 0000 0000 反碼: 1 0111 1111 1111 1111 1111 1111 1111 1111 補(bǔ)碼: 1 1000 0000 0000 0000 0000 0000 0000 0000上面完全是錯(cuò)的,符號(hào)位是指在當(dāng)前系統(tǒng)下的最高那一位,應(yīng)該為:
原碼: -2147483648 1000 0000 0000 0000 0000 0000 0000 0000 1000 0000 0000 0000 0000 0000 0000 0000 反碼: 1111 1111 1111 1111 1111 1111 1111 1111 0111 1111 1111 1111 1111 1111 1111 1111 補(bǔ)碼: 1111 1111 1111 1111 1111 1111 1111 1111 1000 0000 0000 0000 0000 0000 0000 0000字符型:char(注意加單引號(hào)表示Ascii,其他不加或雙引號(hào)跟其他如int、string用法類似)
字符變量的定義和輸出
字符型變量用于存儲(chǔ)一個(gè)單一字符,在 C 語言中用 char 表示,其中每個(gè)字符變量都會(huì)占用 1 個(gè)字節(jié)。在給字符型變量賦值時(shí),需要用一對(duì)英文半角格式的單引號(hào)(' ')把字符括起來。
字符變量實(shí)際上并不是把該字符本身放到變量的內(nèi)存單元中去,而是將該字符對(duì)應(yīng)的 ASCII 編碼放到變量的存儲(chǔ)單元中。char的本質(zhì)就是一個(gè)1字節(jié)大小的整型。
#include <stdio.h>int main() {char ch = 'a';printf("sizeof(ch) = %lu\n", sizeof(ch));printf("ch[%%c] = %c\n", ch); //打印字符printf("ch[%%d] = %d\n", ch); //打印‘a(chǎn)’ ASCII的值char A = 'A';char a = 'a';printf("a = %d\n", a); //97printf("A = %d\n", A); //65printf("A = %c\n", 'a' - 32); //小寫a轉(zhuǎn)大寫Aprintf("a = %c\n", 'A' + 32); //大寫A轉(zhuǎn)小寫ach = ' ';printf("空字符:%d\n", ch); //空字符ASCII的值為32printf("A = %c\n", 'a' - ' '); //小寫a轉(zhuǎn)大寫Aprintf("a = %c\n", 'A' + ' '); //大寫A轉(zhuǎn)小寫areturn 0; }結(jié)果:
sizeof(ch) = 1 ch[%c] = a ch[%d] = 97 a = 97 A = 65 A = A a = a 空字符:32 A = A a = a分析:
1、把‘x’看作一個(gè)字節(jié)的整型數(shù)字
2、小寫字母比大寫字母多32(空格‘ ’)
字符變量的輸入 scanf
#include <stdio.h>int main() {char ch;printf("請(qǐng)輸入ch的值:");//不要加“\n”scanf("%c", &ch);printf("ch = %c\n", ch); //打印ch的字符printf("ch_ascii = %d\n", ch);//打印ch的Ascii碼return 0; }ASCII對(duì)照表(略,自己上網(wǎng)查)
ASCII 碼大致由以下兩部分組成:
- ASCII 非打印控制字符: ASCII 表上的數(shù)字 0-31 分配給了控制字符,用于控制像打印機(jī)等一些外圍設(shè)備。
- ASCII 打印字符:數(shù)字 32-126 分配給了能在鍵盤上找到的字符,當(dāng)查看或打印文檔時(shí)就會(huì)出現(xiàn)。數(shù)字 127 代表 Del 命令。
轉(zhuǎn)義字符 \n \r \b等 (’\123’為8進(jìn)制轉(zhuǎn)義字符,’\x23’為16進(jìn)制轉(zhuǎn)義字符)
注意:紅色字體標(biāo)注的為不可打印字符。
退格鍵\b相當(dāng)于刪除一個(gè)字符
#include <stdio.h>int main() {printf("abc");printf("\refg\n"); //\r切換到句首, \n為換行鍵printf("abc");printf("\befg\n");//\b為退格鍵, \n為換行鍵printf("%d\n", '\123');// '\123'為8進(jìn)制轉(zhuǎn)義字符,0123對(duì)應(yīng)10進(jìn)制數(shù)為83printf("%d\n", '\x23');// '\x23'為16進(jìn)制轉(zhuǎn)義字符,0x23對(duì)應(yīng)10進(jìn)制數(shù)為35return 0; }結(jié)果:
efg abefg 83 35數(shù)值溢出
當(dāng)超過一個(gè)數(shù)據(jù)類型能夠存放最大的范圍時(shí),數(shù)值會(huì)溢出。
有符號(hào)位最高位溢出的區(qū)別:符號(hào)位溢出會(huì)導(dǎo)致數(shù)的正負(fù)發(fā)生改變,但最高位的溢出會(huì)導(dǎo)致最高位丟失。
數(shù)據(jù)類型 占用空間 取值范圍 char 1字節(jié) -128到 127(-27 ~ 27-1) unsigned char 1字節(jié) 0 到 255(0 ~ 28-1) #include <stdio.h>int main() {char ch;//符號(hào)位溢出會(huì)導(dǎo)致數(shù)的正負(fù)發(fā)生改變ch = 0x7f + 2; //127+2printf("%d\n", ch);// 0111 1111//+2后 1000 0001,這是負(fù)數(shù)補(bǔ)碼,其原碼為 1111 1111,結(jié)果為-127//最高位的溢出會(huì)導(dǎo)致最高位丟失unsigned char ch2;ch2 = 0xff+1; //255+1printf("%u\n", ch2);// 1111 1111//+1后 10000 0000, char只有8位最高位的溢出,結(jié)果為0000 0000,十進(jìn)制為0ch2 = 0xff + 2; //255+1printf("%u\n", ch2);// 1111 1111//+1后 10000 0001, char只有8位最高位的溢出,結(jié)果為0000 0001,十進(jìn)制為1return 0; }實(shí)型(浮點(diǎn)型):float、double(能不用則不用,值有時(shí)候不準(zhǔn)確)
實(shí)型變量也可以稱為浮點(diǎn)型變量,浮點(diǎn)型變量是用來存儲(chǔ)小數(shù)數(shù)值的。在C語言中, 浮點(diǎn)型變量分為兩種: 單精度浮點(diǎn)數(shù)(float)、 雙精度浮點(diǎn)數(shù)(double), 但是double型變量所表示的浮點(diǎn)數(shù)比 float 型變量更精確。
數(shù)據(jù)類型 占用空間 有效數(shù)字范圍 float 4字節(jié) 7位有效數(shù)字 double 8字節(jié) 15~16位有效數(shù)字由于浮點(diǎn)型變量是由有限的存儲(chǔ)單元組成的,因此只能提供有限的有效數(shù)字。在有效位以外的數(shù)字將被舍去,這樣可能會(huì)產(chǎn)生一些誤差。
不以 f 結(jié)尾的常量是double類型,以 f 結(jié)尾的常量(如3.14f)是float類型。
#include <stdio.h>int main() {//傳統(tǒng)方式賦值float a = 3.14f; //或3.14Fdouble b = 3.14;printf("a = %f\n", a);printf("b = %lf\n", b);//科學(xué)法賦值a = 3.2e3f; //3.2*1000 = 32000,e可以寫Eprintf("a1 = %f\n", a);a = 100e-3f; //100*0.001 = 0.1printf("a2 = %f\n", a);a = 3.1415926f;printf("a3 = %f\n", a); //結(jié)果為3.141593return 0; }類型限定符 extern const volatile register
限定符 含義 extern 聲明一個(gè)變量,extern聲明的變量沒有建立存儲(chǔ)空間。 extern int a; const 定義一個(gè)常量,常量的值不能修改。 const int a = 10; volatile 防止編譯器優(yōu)化代碼 register 定義寄存器變量,提高效率。register是建議型的指令,而不是命令型的指令,如果CPU有空閑寄存器,那么register就生效,如果沒有空閑寄存器,那么register無效。(現(xiàn)在有些cpu能自動(dòng)優(yōu)化的,那個(gè)這個(gè)就多此一舉了,但是還是需要了解)volatile 是在對(duì)變量連續(xù)賦值的時(shí)候,防止編譯器不經(jīng)過中間值而一步到位,這對(duì)設(shè)計(jì)如跑馬燈之類的程序是不利的,所以需要防止編譯器自動(dòng)優(yōu)化
字符串格式化輸出和輸入
2.9.1 字符串常量
- 字符串是內(nèi)存中一段連續(xù)的char空間,以'\0'(數(shù)字0)結(jié)尾。
- 字符串常量是由雙引號(hào)括起來的字符序列,如“china”、“C program”,“$12.5”等都是合法的字符串常量。
字符串常量與字符常量的不同:
每個(gè)字符串的結(jié)尾,編譯器會(huì)自動(dòng)的添加一個(gè)結(jié)束標(biāo)志位’\0’,即 “a” 包含兩個(gè)字符’a’和’\0’。
printf函數(shù)和putchar函數(shù)
printf是輸出一個(gè)字符串,putchar輸出一個(gè)char。
printf格式字符:
打印格式 對(duì)應(yīng)數(shù)據(jù)類型 含義 %d int 接受整數(shù)值并將它表示為有符號(hào)的十進(jìn)制整數(shù) %hd short int 短整數(shù) %hu unsigned short 無符號(hào)短整數(shù) %o unsigned int 無符號(hào)8進(jìn)制整數(shù) %u unsigned int 無符號(hào)10進(jìn)制整數(shù) %x,%X unsigned int 無符號(hào)16進(jìn)制整數(shù),x對(duì)應(yīng)的是abcdef,X對(duì)應(yīng)的是ABCDEF %f float 單精度浮點(diǎn)數(shù) %lf double 雙精度浮點(diǎn)數(shù) %e,%E double 科學(xué)計(jì)數(shù)法表示的數(shù),此處"e"的大小寫代表在輸出時(shí)用的"e"的大小寫 %c char 字符型。可以把輸入的數(shù)字按照ASCII碼相應(yīng)轉(zhuǎn)換為對(duì)應(yīng)的字符 %s char * 字符串。輸出字符串中的字符直至字符串中的空字符(字符串以'\0‘結(jié)尾,這個(gè)'\0'即空字符) %p void * 以16進(jìn)制形式輸出指針 %% % 輸出一個(gè)百分號(hào)注意:%o 和 %x 說的無符號(hào)指的是指沒有+ -號(hào),它的數(shù)值還是可以表示正負(fù)的
參考:C語言,為什么%o和%x輸出的都是無符號(hào)數(shù),為什呢不能有負(fù)數(shù)
printf附加格式:
字符 含義 l(字母l) 附加在d,u,x,o前面,表示長整數(shù) - 左對(duì)齊 m(代表一個(gè)整數(shù)) 數(shù)據(jù)最小寬度 0(數(shù)字0) 將輸出的前面補(bǔ)上0直到占滿指定列寬為止不可以搭配使用- m.n(代表一個(gè)整數(shù)) m指域?qū)?#xff0c;即對(duì)應(yīng)的輸出項(xiàng)在輸出設(shè)備上所占的字符數(shù)。n指精度,用于說明輸出的實(shí)型數(shù)的小數(shù)位數(shù)。對(duì)數(shù)值型的來說,未指定n時(shí),隱含的精度為n=6位。 #include <stdio.h> int main() {int a = 100;printf("a = %d\n", a);//格式化輸出一個(gè)字符串printf("%p\n", &a);//輸出變量a在內(nèi)存中的地址編號(hào)printf("%%d\n");char c = 'a';putchar(c);//putchar只有一個(gè)參數(shù),就是要輸出的charlong a2 = 100;printf("%ld, %lx, %lo\n", a2, a2, a2);long long a3 = 1000;printf("%lld, %llx, %llo\n", a3, a3, a3);int abc = 10;printf("abc = '%6d'\n", abc);printf("abc = '%-6d'\n", abc);printf("abc = '%06d'\n", abc);printf("abc = '%-06d'\n", abc);double d = 12.3;printf("d = \' %-10.3lf \'\n", d);printf("d = \' %-5.3lf \'\n", d);return 0; }結(jié)果:
dontla@dontla-virtual-machine:~/桌面/c_code/day03$ gcc test06.c test06.c: In function ‘main’: test06.c:21:9: warning: '0' flag ignored with '-' flag in gnu_printf format [-Wformat=]21 | printf("abc = '%-06d'\n", abc);| ^~~~~~~~~~~~~~~~~ dontla@dontla-virtual-machine:~/桌面/c_code/day03$ ./a.out a = 100 0x7ffc7eae3368 %d a100, 64, 144 1000, 3e8, 1750 abc = ' 10' abc = '10 ' abc = '000010' abc = '10 ' d = ' 12.300 ' d = ' 12.300 ' //上面兩個(gè)什么操作看不懂呢???(Dontla:m.n右邊數(shù)字n的優(yōu)先級(jí)高于左邊,當(dāng)發(fā)生沖突時(shí),優(yōu)先保證n不保證m【注意,對(duì)于m來說,小數(shù)點(diǎn)也占一位】) //m.n(代表一個(gè)整數(shù)) m指域?qū)?#xff0c;即對(duì)應(yīng)的輸出項(xiàng)在輸出設(shè)備上所占的字符數(shù)。n指精度,用于說明輸出的實(shí)型數(shù)的小數(shù)位數(shù)。對(duì)數(shù)值型的來說,未指定n時(shí),隱含的精度為n=6位。?0不能和 - 同時(shí)使用,因?yàn)?- 代表左對(duì)齊,如果沒有小數(shù)點(diǎn)的話,后面補(bǔ)零,數(shù)值就不對(duì)了。
示例:
putchar示例(輸出字符,隱藏很深!)
示例1:
#include <stdio.h> #include <stdlib.h> int main() {char c = 'a';printf("%d\n", putchar(c)); \\a97printf("%d\n", c); \\97putchar(c);printf("%d\n", 1111111); \\a1111111return 0; }示例2:
#include <stdio.h> int main() {putchar('a');return 0; }scanf函數(shù)與getchar函數(shù)
- getchar是從標(biāo)準(zhǔn)輸入設(shè)備讀取一個(gè)char。
- scanf通過%轉(zhuǎn)義的方式可以得到用戶通過標(biāo)準(zhǔn)輸入設(shè)備輸入的數(shù)據(jù)。
scanf示例
示例1:用scanf取數(shù)字
#include <stdio.h> int main() { int a;int b;printf("請(qǐng)輸入字符a:\n");scanf("%d", &a);printf("請(qǐng)輸入字符b:\n");scanf("%d", &b);printf("%d %d\n", a, b);return 0; }結(jié)果:
請(qǐng)輸入字符a: 5 請(qǐng)輸入字符b: 6 5 6示例2:用scanf取字符(換行符 \n 會(huì)被吃掉)(\n 的ascii碼是10)
#include <stdio.h> int main() { char a;char b;printf("請(qǐng)輸入字符a:\n");scanf("%c", &a);printf("請(qǐng)輸入字符b:\n");scanf("%c", &b);printf("%c %c\n", a, b);printf("%d %d\n", a, b);return 0; }結(jié)果:
請(qǐng)輸入字符a: h 請(qǐng)輸入字符b: h 104 10getchar函數(shù)示例(鍵盤輸入時(shí),貌似比scanf好用)
#include <stdio.h>int main() {char ch1;char ch2;char ch3;int a;int b;printf("請(qǐng)輸入ch1的字符:");ch1 = getchar();printf("ch1 = %c\n", ch1);getchar(); //測試此處getchar()的作用printf("請(qǐng)輸入ch2的字符:");ch2 = getchar();printf("\'ch2 = %ctest\'\n", ch2);getchar(); //測試此處getchar()的作用printf("請(qǐng)輸入ch3的字符:");scanf("%c", &ch3);//這里第二個(gè)參數(shù)一定是變量的地址,而不是變量名printf("ch3 = %c\n", ch3);printf("請(qǐng)輸入a的值:");scanf("%d", &a);printf("a = %d\n", a);printf("請(qǐng)輸入b的值:");scanf("%d", &b);printf("b = %d\n", b);return 0; }結(jié)果:
請(qǐng)輸入ch1的字符:a ch1 = a 請(qǐng)輸入ch2的字符:b 'ch2 = btest' 請(qǐng)輸入ch3的字符:c ch3 = c 請(qǐng)輸入a的值:6 a = 6 請(qǐng)輸入b的值:8 b = 8https://www.bilibili.com/video/BV15W411K7k6?p=93&spm_id_from=pageDriver
總結(jié)
以上是生活随笔為你收集整理的黑马程序员C语言基础(第四天)数据类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: visual studio快捷键 Qt
- 下一篇: qt creator创建cmake构建的