文章程式碼顯示

2019年9月7日 星期六

《筆記》C語言 - 補充_10: 再戰指標變數、struct 結構 與 void* 的結合


#include "stdio.h"

int main()
{
    typedef struct{
        int pool_1;
        int pool_2;
    }money_pool_small,*PTR_money_pool_small;
    
    typedef struct{
        int pool_3;
        int pool_4;
        int pool_5;
        int pool_6;
    }money_pool_big,*PTR_money_pool_big;
    
    money_pool_small _money_pool_small = {0x1234, 0x5678};
    money_pool_big _money_pool_big = {0x7564, 0x8546, 0x5217, 0x9812};
    
    
    /* 取一個 struct 最基本的寫法 */
    int value;
    value = _money_pool_small.pool_1;
 //get 0x1234 (address = 0xfab6ed78)  
    printf("value = 0x%x (address = 0x%x) \r\n", value, &(_money_pool_small.pool_1)); 
    value = _money_pool_small.pool_2;
 //get 0x5678 (address = 0xfab6ed7c)  
    printf("value = 0x%x (address = 0x%x) \r\n", value, &(_money_pool_small.pool_2)); 

    /* 使用對應的 struct指標 取 struct 數值 */
    PTR_money_pool_small _PTR_money_pool_small = NULL;
    _PTR_money_pool_small = (&_money_pool_small);
    value = _PTR_money_pool_small->pool_1; 
    printf("value = 0x%x \r\n", value); //get 0x1234
    value = _PTR_money_pool_small->pool_2;
    printf("value = 0x%x \r\n", value); //get 0x5678
    
    /* 使用一般的指標變數 取 struct 數值*/
    int* ptr_pool_int = NULL;
    ptr_pool_int = (&_money_pool_small); //取到的是 _money_pool_small 啟始位址
    value = (*ptr_pool_int);
    printf("value = 0x%x \r\n", value); //get 0x1234
    
    ptr_pool_int++; // 指標遞增
    value = (*ptr_pool_int); 
    printf("value = 0x%x \r\n\n", value); //get 0x5678
    
    /* 使用位元數比 struct 內數值小的一般指標變數 取 struct 數值*/
    char* ptr_pool_char = NULL;
    ptr_pool_char = (&_money_pool_small); //取到的是 _money_pool_small 啟始位址
    value = (*ptr_pool_char);
 //get 0x34 (address = 0xfab6ed78)
    printf("value = 0x%x (address = 0x%x) \r\n", value, ptr_pool_char); 
    
    ptr_pool_char++; // 指標遞增
    value = (*ptr_pool_char); 
 //get 0x12 (address = 0xfab6ed79)
    printf("value = 0x%x (address = 0x%x) \r\n\n", value, ptr_pool_char); 
    /********************************************************************
    * 由此我們可以得知, _money_pool_small 的 pool_1 兩個 bytes 的資料(0x1234)在
    * 記憶體中是將低位元(0x34)放置於低地址,此稱為 Little-Endian (小端格式)
    * 而與此對應的有 big-endian (大端格式) 其反將高位元(0x12)放置於低地址
    * 也就是說 big-endian 將一個 int 變數其四個 byte 在記憶體中是 "倒著放的" 
    * (但兩個不同的變數在記憶體中仍是 "順著放的")
    * PS : x86 系列的 CPU 都是 little-endian
    *********************************************************************/
    
    /* 將 int* 轉為 char* 取 struct 數值*/
    int* ptr_pool_int_1 = NULL;
    ptr_pool_int_1 = (&_money_pool_small); //先指向位址,後續要取值時再強制轉型
    value = ( *( (char*) ptr_pool_int_1) ); //注意指標強制轉型的時機與對象以及括弧位置的重要
    printf("value = 0x%x \r\n", value); //0x34
    
    ptr_pool_int_1++;
    value = ( *( (char*)ptr_pool_int_1) ); 
    printf("value = 0x%x \r\n", value); //0x78
    
    /* 使用空指標並強制轉型為一般指標變數 取 struct 數值*/
    void* ptr_pool_void = NULL;
    ptr_pool_void = (&_money_pool_small); //先指向位址,後續要取值時再強制轉型
    value = ( *( (int*)ptr_pool_void ) ); //注意指標強制轉型的時機與對象以及括弧位置的重要
    printf("value = 0x%x \r\n", value); //0x1234
    
    /* 以 PTR_money_pool_small 對 _money_pool_big 取值 */
    PTR_money_pool_small ptr_money_pool_small = NULL;
    ptr_money_pool_small = (&_money_pool_big);
    value = ptr_money_pool_small->pool_1; 
    printf("value = 0x%x \r\n", value); //0x7564
    
    // 指標遞增(假設 int 變數佔據 4bytes, 則此時地址一次是跳8個byte)
    ptr_money_pool_small++; 
    value = ptr_money_pool_small->pool_1;//此時 pool_1 對應到的是 money_pool_big 的 pool_3
    printf("value = 0x%x \r\n", value); //0x5217
    
    /* 使用空指標並強制轉型為 PTR_money_pool_small 取 _money_pool_big (struct) 數值*/
    ptr_pool_void = NULL;
    ptr_pool_void = (&_money_pool_big);
    
    value = ( *( (PTR_money_pool_small)ptr_pool_void ) ).pool_1;
    printf("value = 0x%x \r\n", value); //0x7564
    value = ( (PTR_money_pool_small)ptr_pool_void )->pool_1; //與上上行的寫法等價
    printf("value = 0x%x \r\n", value); //0x7564
    
    
    return 0;
}





我的 Youtube 頻道,一定要訂閱
我將定期推出程式語言的新手教學影片


↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引