數據在內存的存儲形式

第一:數據類型分類

1.1 基本內置類型

類型 別名 所佔字節 解釋
char signed char 1 字符數據
short signed short [int] 2 短整型
int signed [int] 4 整型
long signed long [int] 4 長整型
long long signed long long [int] 8 長長整型
float - 4 單精度浮點型
double - 8 雙精度浮點型
long double - 8 長雙精度浮點型
#include <stdio.h>
int main()
{
    printf("char        %d\n", sizeof(char));
    printf("short       %d\n", sizeof(short));
    printf("int         %d\n", sizeof(int));
    printf("long        %d\n", sizeof(long));
    printf("long long   %d\n", sizeof(long long));
    printf("float       %d\n", sizeof(float));
    printf("double      %d\n", sizeof(double));
    printf("long double %d\n", sizeof(long double));
    return 0;
}

數據在內存的存儲形式

1.2 取值範圍

類型 最小值 最大值 最小值 最大值
char -2^7 2^7-1 SCHAR_MIN:-128 SCHAR_MAX:127
unsigned char 0 2^8-1 0 UCHAR_MAX:0xff/255
short -2^15 2^15-1 SHRT_MIN:-32768 32767
unsigned short 0 2^16-1 0 USHRT_MAX:0xffff/65535
int -2^31 2^31-1 INT_MIN:-2147483648 INT_MAX:2147483647
unsigned int 0 2^32-1 0 UINT_MAX:0xffffffff/4294967295
long -2^31 2^31-1 LONG_MIN:-2147483648L LONG_MAX:2147483647L
unsigned long 0 2^32-1 0 ULONG_MAX:0xffffffffUL/4294967295L
long long -2^63 2^63-1 LLONG_MIN:-9223372036854775807i64 - 1 LLONG_MAX:9223372036854775807i64
unsigned long long 0 2^64-1 0 ULLONG_MAX:0xffffffffffffffffui64
#include <stdio.h>
#include <stdlib.h>
int main()
{
    printf("char min and max                  = %d\t\t%d\n", SCHAR_MIN, SCHAR_MAX);
    printf("unsigned char min and max  = %d\t\t%d\n", 0, UCHAR_MAX);
    printf("short min and max                 = %d\t\t%d\n", SHRT_MIN, SHRT_MAX);
    printf("unsigned short min and max = %d\t\t%d\n", 0, USHRT_MAX); 
    printf("int min and max                     = %d\t\t%d\n", INT_MIN, INT_MAX);
    printf("unsigned int min and max     = %d\t\t%#x\n", 0, UINT_MAX);
    printf("long min and max                  = %ld\t\t%ld\n", LONG_MIN, LONG_MAX);
    printf("unsigned long min and max  = %d\t\t%#x\n", 0, ULONG_MAX);
    printf("long long min and max           = %lld\t\t%lld\n", LLONG_MAX, LLONG_MAX);
    printf("unsigned long long min and max  = %d\t\t%llu\n", 0, ULLONG_MAX);
    return 0;
}

數據在內存的存儲形式

1.3 構造數據

類型 關鍵字
數組 []
結構體 struct
聯合體 union
枚舉 enum

1.4 指針和空類型

指針類型是指在類型後面加上一顆*,表示,好比:int* p;表示p是一個整型指針,指向的內存空間爲int。
    空指針:void *,好比內存函數:malloc calloc等函數的返回值都爲void*類型,須要強制將其轉化爲指定類型的指針,如:int arr = (int*)malloc(10 * sizeof(10)),即申請了10個int的內存空間。

第二:整型的存儲方式

2.1 存儲方式:

整型數據在內存中是以補碼的方式進行存儲的。
整型:算法

  1. 有符號位的整型
    1.1. 正數:原碼=反碼=補碼
    1.2. 負數:反碼=原碼的除符號位以外,其他位取反,補碼 = 反碼+1
  2. 無符號位整型:原碼=反碼=補碼

    2.2 大小端存儲方式

    是指字節在內存中存放的順序。
    分爲大端存儲(大端字節存儲)和小端存儲(小端字節存儲)
Column 1 內存低地址 內存高地址
小端 數據補碼的低位 數據補碼的高位
大端 數據補碼的高位 數據補碼的低位

判斷系統是以哪一種方式存放數據的。
以下面例子:
數據在內存的存儲形式數組

// 小端:返回1,大端:返回0
int check_sys()
{
    int a = 1;
    char* p = (char*)&a;
    if (1 == *p)
    {
        return 1;
    }
    else
    { 
        return 0;
    }
}

// 小端:返回1,大端:返回0
int check_sys_v1()
{
    int a = 1;
    char* p = (char*)&a;
    return *p; // 由於*p == 1,返回1,*p == 0,返回0,因此直接返回*p
}

// 小端:返回1,大端:返回0
int check_sys_v2()
{
    int a = 1;
    return *(char*)&a; // 由於*p == 1,返回1,*p == 0,返回0,因此直接返回*p
}

int main()
{
    int a = 1024;
    int ret = check_sys_v2(a);
    if (0 == ret)
    {
        printf("大端字節模式\n");
    }
    else
    {
        printf("小端字節模式\n");
    }
    return 0;
}

數據在內存的存儲形式

2.2.1 例1:

int main()
{
    char a = -1;  // 由於a是char類型,只佔1個字節,且是小端字節存儲模式,因此將-1的補碼的低8位所佔的字節上的值截取給char a:11111111
    signed char b = -1;   // signed char b 等價於char a
    unsigned char c = -1; // c存的補碼也是11111111,可是爲無符號的整型,則原碼=反碼=補碼,故原碼爲11111111,即255
    // 11111111111111111111111111111111  - -1的補碼
    // 由於a是char類型,只佔1個字節,且是小端字節存儲模式,因此將存放在低地址中的a的低數據位中的8個比特位截取給a
    // 故 a = 11111111 - 補碼
    // b是signed char 能夠簡寫爲char b,故與a數據類型相同
    // 故 b = 11111111 - 補碼
    // 因爲c也是char類型
    // 故 c = 11111111 - 補碼 
    // 由於打印時,是以整型進行打印的,因此須要作提高(按照原符號位進行提高)
    // 因爲a是有符號的,且符號位1,則補1,即爲:11111111111111111111111111111111,
    //    前24個1爲補的1,則其原碼爲1000...0001,爲-1
    // b和a都爲有符號的char,故他們相同
    // c是無符號的char,則補0進行提高,即爲00000000000000000000000011111111,其原碼=反碼=補碼,故爲255
    printf("a = %d,b = %d,c = %d\n", a, b, c);
    return 0;
}

數據在內存的存儲形式

2.2.2 例2:

int main()
{
    char a = -128;
    // 10000000 00000000 00000000 10000000 - 原碼
    // 11111111 11111111 11111111 01111111 - 反碼
    // 11111111 11111111 11111111 10000000 - 補碼
    // a 爲char佔一個字節:因此截取低地址所存取的值(數據的低位):10000000
    // char a:10000000
    // %u爲無符號的整型,因此要作提高,因爲char a爲有符號,因此提高位補1:
    // 11111111 11111111 11111111 10000000 (提高後),提高後爲無符號,因此其原碼=反碼=補碼其對應的十進制爲;4294967168
    printf("%u\n", a); 
    return 0;
}

數據在內存的存儲形式

2.2.3 例3:

int main()
{
    char a = 128;
    // 00000000 00000000 00000000 10000000 - 原碼=反碼=補碼

    // a 爲char佔一個字節:因此截取低地址所存取的值(數據的低位):10000000
    // char a:10000000
    // %u爲無符號的整型,因此要作提高,因爲char a爲有符號,因此提高位補1:
    // 11111111 11111111 11111111 10000000 (提高後),提高後爲無符號,因此其原碼=反碼=補碼其對應的十進制爲;4294967168
    printf("%u\n", a); 
    return 0;
}

數據在內存的存儲形式

2.2.4 例4:

int main()
{
    //9 8 7 6 5 4 3 2 1 0 2^32-1 ...0 2 ^ 32 - 1 ...0往復進行死循環
    // 由於當i==0時打印後,執行i--;即i = 0-1 = 0 + (-1) = 32個1
    // i 爲無符號整型,因此原碼和補碼相同,即i爲2^32-1
    unsigned int i;
    for (i = 9; i >= 0; i--)
    {
        printf("%u\n", i);
    }
}

2.2.5 例5:

int main()
{
    char a[1000];
    int i;
    for (i = 0; i <= 1000; i++)
    {
        a[i] = -1 - i; // -1 -2 .. -128 127 126 ... 1 0 -1 ....
    }
    printf("%d\n", strlen(a)); // 遇到0中止
    return 0;
}

unsigned char i = 0;
int main()
{
    for (i = 0; i <= 255; i++)
    {
        printf("hello, world %d\n", i);0 .. 255 0 .. 255 ...死循環
    }
    return 0;
}

第三:浮點數在內存的存數形式

3.1 國際標準:

根據國際標準IEEE(電氣和電子工程協會)754規定,能夠將任何一個浮點數(二進制)表示爲如下的通用形式:

3.1.1 公式:

(-1)^S * M * 2^E
註釋:
        1. (-1)^S表示符號位,負數:S = 1;正數:S = 0;
        2. M:表明有效位數(科學計數法),1 <= M < 2;
        3. 2^E:表明指數位數(E),如2^4,E = 4;

S M E存放順序和大小:

(1)對於32位的浮點數:float(佔4個字節,32個比特位)S M E的存放順序和大小爲:
         低地址--->高地址:
         S:存放第一位(1位);E:存放2-9位(8位);M:存放10-32位(23位)。
       (2)對於64位的浮點數:double(佔8個字節,64個比特位)S M E的存放順序和大小爲:
        低地址--->高地址:
         S:存放第一位(1位);E:存放2-12位(11位);M:存放13-64位(52位)。

3.2 浮點數轉爲二進制的算算法步驟:

(1)整數部分(除2):如:13:
            13 / 2 = 6 ... 1
            6   / 2 = 3 ... 0
            3   / 2 = 1 ... 1
            1  /  2 = 0 ... 1 # 當商爲0時,中止運算,將一次獲得的餘數做爲二進制的低位-->高位數據,如:13:1101 

    (2)小數部分(乘2):如0.875
            0.875 * 2 = 1.750 = 1 + 0.75 # 二進制中的左邊第一個1
            0.75 * 2   = 1.50 = 1 + 0.5     # 二進制中左邊第二個1
            0.5 * 2 = 1.0 = 1 + 0 # 當相乘後小數位0,則中止計算將依次獲得整數位做爲小數二進制的高位-->低位,如:111

    如:13.5的二進制爲:00001101.1,即1101.1
    將其轉化爲IEEE754標準:(-1) ^ 0 * 1.1011 * 2 ^ 3
    即:S = 0;M = 1.1011;E = 3

3.3 S M E 在內存中存放的值

(1)S
            若是爲正數:S在內存中存放的是0
            若是是負數:S在內存中存放的是1
(2)M
            將M的小數部分存放在內存中。
 (3)E
         E是一個無符號正數;float(8爲:0-255);double(11位:0-2047);
因爲E能夠是負數,當浮點數小於1時,因此存入內存中的E爲真實的E加上一個中間數(double:1023;float:127),即:內存中E = 二進制E + 127 or 1023.
如:float的13.875的二進制:1.1011中的E爲3,則內存中爲3 + 127 = 128 + 2 = 10000010(2^7 + 2 ^ 1)
    例如:
           13.875在內存中的存放爲:
            二進制爲:1101.111
            IEEE754:(-1) ^ 0 * 1.101111 * 2 ^ 3, S = 0;M = 1.1011;E = 3
            內 存  爲:0 10000010 10111100000000000000000
                          :0100 0001 0101 1110 0000 0000 0000 0000
            十六進制:41 5e 00 00,即:0x415e0000
            內存爲   : 00 00 5e 41(低地址-->高地址)

數據在內存的存儲形式

3.4 去讀數據

(1)當E(內存中的E)中同時存在1和0
            其值-127或者1023獲得的是IEEE754中公式中的E。
            內中的M中爲小數(xxxx),將其加上1,變爲1.xxxx
            正數:S= 0;負數:S=1
      (2)E(內存中的E)爲全0 爲一個無窮小的數字
            真是的E爲1-127 or 1 - 1023
            M:不在加上正數部的1. 0.xxxx
           S:同上
    (3)E(內存中的E)爲全1,若是有效數字全爲0,則表示無窮大數字。

3.5 例子解析

int main()
{

    // 00000000 00000000 00000000 00000110 - 6的補碼
    // 當以float輸出時,上述爲浮點數的補碼,將其進行讀取爲:S = 0;E = 1 - 126;M = 0.11 爲一個無窮小的數
    int a = 6;
    float* p = (float*)&a;
    printf("a = %d\n", a); // 6
    printf("*p = %f\n", *p); // 0.0000000

    // 6.0的二進制:110.0 -->IEEE754: (-1)^0 * 1.10 * 2 ^ 2
    // S = 0;M = 1.10;E = 2;2 + 127 = 10000001;
    // 內存:01000000 11000000 00000000 00000000
    // 因此當以整型進行輸出時:爲01000000 11000000 00000000 00000000,爲正數,即爲原碼:
    *p = 6.0;
    printf("a = %d\n", a); // 01000000110000000000000000000000,十進制:1,086,324,736
    printf("*p = %f\n", *p); // 6.0
    return 0;
}

數據在內存的存儲形式

相關文章
相關標籤/搜索