@toc 編程
自定義函數是系統不自帶的,經過本身的編寫後可使用的函數。通常的編程語言、工做表等均可以編寫自定義函數使用。
編寫自定義函數能夠簡化主程序,讓程序的檢查調試更方便小程序
類型的意義,能夠從如下兩個角度考慮:windows
1.使用這個類型開闢內存空間的大小(大小決定了使用範圍)markdown
好比說使用
char類型
建立的變量,開闢的內存空間是1個字節
,使用int類型
建立的變量,開闢的內存空間是4個字節
。編程語言
2.如何看待內存空間的視角ide
好比:
int a = 0;
float b = 0.0;
雖然 a, b都是佔用4個字節的空間,可是咱們在看待a的時候,由於其類型是int,因此咱們會把a當作整型來看待,在看待b的時候,由於其類型是float,因此咱們會把b當作小數(而非整型)來看待。函數
例:翻譯
以前講過 一個變量的建立是要在內存中開闢空間的。空間的大小是根據不一樣的類型而決定的。設計
那接下來咱們談談
數據在所開闢內存中究竟是如何存儲的?
3d
看下面這個例子:
#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 接下來下面講:
下面先來了解幾個概念︰原碼、反碼、補碼
計算機中的有符號數有三種表示方法,即原碼、反碼和補碼。
三種表示方法均有符號位和數值位兩部分,符號位都是用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/>無符號數 --- 原反補按規則計算
數據存放內存中其實存放的是補碼。
咱們首先來看一下 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
大端(存儲)模式,是指數據的低位保存在內存的高地址中,而數據的高位,保存在內存的低地址中。
小端(存儲)模式,是指數據的低位保存在內存的低地址中,而數據的高位,,保存在內存的高地址中。
#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 --- 正整數是同樣的!(只能表示正整數!)
無符號數 --- 原反補按規則計算
數據存取過程圖解:
爲何會有大小端模式之分呢 ?
這是由於在計算機系統中,咱們是以字節爲單位的,每一個地址單元都對應着一個字節,一個字節爲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; }