@toc
一、資料類型詳細介紹(從大方向分為兩種類型)
1.内置類型(C語言本身庫有函數)
2.構造類型(自定義函數)
自定義函數是系統不自帶的,通過自己的編寫後可以使用的函數。一般的程式設計語言、工作表等都可以編寫自定義函數使用。
編寫自定義函數可以簡化主程式,讓程式的檢查調試更友善
3.類型的意義
類型的意義,可以從以下兩個角度考慮:
1.使用這個類型開辟記憶體空間的大小(大小決定了使用範圍)
比如說使用建立的變量,開辟的記憶體空間是
char類型
,使用
1個位元組
int類型
。
4個位元組
2.如何看待記憶體空間的視角
比如:
int a = 0;
float b = 0.0;
雖然 a, b都是占用4個位元組的空間,但是我們在看待a的時候,因為其類型是int,是以我們會把a當做整型來看待,在看待b的時候,因為其類型是float,是以我們會把b當做小數(而非整型)來看待。
二、資料類型細分類
1.整形家族
2.浮點型家族
3.構造類型
4.指針類型
5.空類型
例:
三、整型在記憶體中的存儲
之前講過 一個變量的建立是要在記憶體中開辟空間的。空間的大小是根據不同的類型而決定的。
那接下來我們談談 資料在所開辟記憶體中到底是如何存儲的?
1. 如何儲存
看下面這個例子:
#include<stdio.h>
int main()
{
int a = 3;
int b = -1;
return 0;
}
為了檢視a, b在記憶體中的存儲形式,我們在編譯器裡面按F10進入調試,變量a,b建立後,打開記憶體螢幕,輸入& a,& b檢視a,b對應的位址及其内容。
& a:
&b:
資料在記憶體中存儲時是按二進制的補碼存儲的
展示記憶體的時候,為了友善展示,
顯示的是16進制資料
什麼意思呢? 我們定義一個變量c,以16進制形式對其指派,然後& c,可以看到:
c輸入的16進制形式是 11223344 ,存儲的時候是 44332211 接下來下面講:
2. 原碼、反碼、補碼
下面先來了解幾個概念︰原碼、反碼、補碼
計算機中的有符号數有三種表示方法,即原碼、反碼和補碼。
三種表示方法均有符号位和數值位兩部分,符号位都是用0表示′正”,用1表示"負”,而數值位三種表示方法各不相同。
原碼:直接将二進制按照正負數的形式翻譯成二進制就可以。
反碼:将原碼的符号位不變,其他位依次按位取反就可以得到了。
補碼:反碼 + 1就得到補碼。
正數
原碼反碼補碼
三碼合一
,
負數
的原反補
按照上面的規則進行轉換
整數有兩種,有符号數和無符号數
有符号數-- - 符号位 + 數值位
正數 0 + 數值位
負數 1 + 數值位
int b = -1;
//10000000 00000000 00000000 00000001 - 原碼
//11111111 11111111 11111111 11111110 - 反碼
//11111111 11111111 11111111 11111111 - 補碼
//ff ff ff ff - 十六進制顯示形式
int a = 3;
//00000000 00000000 00000000 00000011 - 原碼、反碼、補碼
//0000 0000 0000 0000 0000 0000 0000 0000 0000 0011
//00 00 00 03 - 十六進制顯示形式
無符号數 unsigned --- 正整數是一樣的!(隻能表示正整數!)<br/>無符号數 --- 原反補按規則計算
資料存放記憶體中其實存放的是補碼。
3. 為什麼記憶體中要存儲補碼?
我們首先來看一下 1 - 1 這個例子:
①先按照原碼的方式去計算。
②接下來用補碼來進行計算:
在計算機系統中,數值一律用補碼來表示和存儲
。原因在于,使用補碼,可以将符号位和數值域統一處理; 同時,加法和減法也可以統一處理(CPU隻有加法器)此外,補碼與原碼互相轉換,其運算過程是相同的,不需要額外的硬體電路。
怎麼了解補碼與原碼互相轉換,其運算過程是相同的?(以下運算,符号位均不變)
原碼->取反 + 1->補碼
補碼->取反 + 1->原碼
當然補碼到原碼也可以是:補碼 -> - 1 取反->原碼
例如 - 1:
11111111 11111111 11111111 11111111 - 補碼
補碼->取反 + 1->原碼
10000000 00000000 00000000 00000000 - 取反
10000000 00000000 00000000 00000001 - +1
補碼 -> - 1 取反->原碼
11111111 11111111 11111111 11111110 - -1
10000000 00000000 00000000 00000001 - 取反
最終得到的結果均是:10000000 00000000 00000000 00000001
四、大小端介紹
1.什麼大端小端
大端(存儲)模式,是指資料的低位儲存在記憶體的高位址中,而資料的高位,儲存在記憶體的低位址中。
小端(存儲)模式,是指資料的低位儲存在記憶體的低位址中,而資料的高位,,儲存在記憶體的高位址中。
#include <stdio.h>
#include <windows.h>
int main()
{
unsigned int a = -10;
printf("%d\n", a);//%d有符号數列印
printf("%u\n", a);//%u無符号數列印
system("pause");
return 0;
}
對上述代碼能運作的解釋
存:
1000 0000 0000 0000 0000 0000 0000 1010 ->原碼
1111 1111 1111 1111 1111 1111 1111 0101 ->反碼
1111 1111 1111 1111 1111 1111 1111 0110 ->補碼
//因為是int類型,是以在記憶體存儲32位
即 0xfffffff6
那麼如何存呢?
可以看出是小端存儲。
解析:
無符号數 unsigned --- 正整數是一樣的!(隻能表示正整數!)
無符号數 --- 原反補按規則計算
資料存取過程圖解:
2.為什麼有大端和小端
為什麼會有大小端模式之分呢 ?
這是因為在計算機系統中,我們是以位元組為機關的,每個位址單元都對應着一個位元組,一個位元組為8bit。
但是在C語言中除了8bit的char之外,還有16bit的short型,32bit的long型(要看具體的編譯器)。
另外,對于位數大于8位的處理器,例如16位或者32位的處理器,由于寄存器寬度大于一個位元組,那麼必然存在着一個如果将多個位元組安排的問題。
是以就導緻了大端存儲模式和小端存儲模式。
例如一個16bit的short型x,在記憶體中的位址為ox0010),x的值為0×1122,那麼0x11為高位元組,0x22為低位元組。對于大端模式,就将0x11放在低位址中,即0x0010中,0x22放在高位址中,即0x0011中。小端模式,剛好相反
我們常用的x86結構是小端模式,而KEIL c51則為大端模式。很多的ARM,DSP都為小端模式。有些ARM處理器還可以由硬體來選擇是大端模式還是小端模式。
筆試題:用小程式判斷目前機器的位元組序(大小端)
百度2015年系統工程師筆試題:
請簡述大端位元組序和小端位元組序的概念,設計一個小程式來判斷目前機器的位元組序
如何判斷大端、小端(位元組序)呢?
思路:
int a = 1;
将a的第一個位元組内容拿出來,判斷其是1還是0,1為小端,0為大端。
char* 儲存一個位元組
#include <stdio.h>
int check_sys()
{
int i = 1;
//對指針i解引用,可以找存儲的第一個位元組
//如果得到01,說明存儲的順序是01 00 00 00,則為小端,
//如果得到00,說明存儲的順序是00 00 00 01,則為大端,
return (*(char *)&i);
}
int main()
{
int ret = check_sys();
if(ret == 1)//0x00 00 00 01
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
int check_sys()
{
int a = 1;
char* p = (char*)&a;
if (*p == 1)
return 1;//小端
else
return 0;//大端
}
int check_sys()
{
int a=1;
char*p=(char*)&a;
//傳回1,小端
//傳回0,大端
return *p;
}
int check_sys()
{
int a = 1;
return *(char*)&a;
}