2015-04-03 60 views
0

我試圖使用指針來移動一個充滿十六進制值的內存區域。我使用的是uint8_t指針,以確保它一次只指向1個字節。我想要轉到特定位置(從起始位置偏移字節數)並存儲一組長度爲1,2,4或8個字節的字節。然後我想解釋並打印該值作爲有符號或無符號十進制(由枚舉參數確定)。類型轉換指針來改變其大小(以字節爲單位)

我認爲我可以簡單地將指針從1字節的uint8_t更改爲字節數的正確大小(例如對於8 btyes的uint64_t),然後存儲該值(因爲我不能只是打印它一次一個字節,我需要評估整個字節/一組字節)。這是我到目前爲止有:

void showValueAtOffset(FILE* Out, const uint8_t* const baseAddr, uint32_t Offset, Sign Sgn, uint8_t nBytes) {//------------------doesn't work---------------- 
    uint8_t *p = baseAddr;//create a pointer that points to the first byte of memory in the array 
    for(int i = 0; i < Offset; i++){//use a for loop to move p to the location indicated by Offset 
     p++; 
    } 
    if(nBytes == 1){ 
     //pointer p already has the correct typecast for the number of bytes 
     uint8_t N = *p;//store the value of the byte 
     if(Sgn == SIGNED){ 
      int8_t result = N; 
      fprintf(Out, "%d ", result);//print the value 
     } 
     else{//if UNSIGNED 
      fprintf(Out, "%u ", N);//print the value 
     } 
    } 
    else if(nBytes == 2){ 
     uint16_t q = (uint16_t) p;//create the pointer q with the correct typecast for the number of bytes 
     uint16_t N = *q;//store the value of the bytes 
     if(Sgn == SIGNED){ 
      int16_t result = N; 
      fprintf(Out, "%d ", result);//print the value 
     } 
     else{//if UNSIGNED 
      fprintf(Out, "%u ", N);//print the value 
     } 
    } 
    else if(nBytes == 4){ 
     uint32_t q = (uint32_t) p;//create the pointer q with the correct typecast for the number of bytes 
     uint32_t N = *q;//store the value of the bytes 
     if(Sgn == SIGNED){ 
      int32_t result = N; 
      fprintf(Out, "%d ", result);//print the value 
     } 
     else{//if UNSIGNED 
      fprintf(Out, "%u ", N);//print the value 
     } 
    } 
    else if(nBytes == 8){ 
     uint64_t q = (uint64_t) p;//create the pointer q with the correct typecast for the number of bytes 
     uint64_t N = *q;//store the value of the bytes 
     if(Sgn == SIGNED){ 
      signed int result = (signed int) N; 
      fprintf(Out, "%d ", result);//print the value 
     } 
     else{//if UNSIGNED 
      unsigned int result = (unsigned int) N; 
      fprintf(Out, "%u ", result);//print the value 
     } 
    } 
    else{ 
     //this should not happen according to the preconditions 
    } 
    fprintf(Out, "\n"); 
} 

這不工作,我得到一些錯誤,如「無效的類型arguement‘一元*’(有‘uint32_t的’)」和「警告:一個指針轉換爲整數大小不同「。

我在做什麼錯?

+0

您正在將'uint8_t *'轉換爲'uint32_t'(例如),失去了該類型的指向性。你仍然需要擔心指針的對齊。在許多機器上,如果它沒有指向8字節的邊界(地址不是8的倍數),那麼你不能使用'uint64_t *',否則你的訪問會變得非常嚴重。 (例如,在DEC Alpha中,一個未對齊的訪問觸發了一個系統調用,它可以爲你解決問題,但是比對齊訪問慢得多,通常根本不需要系統調用。) – 2015-04-03 23:36:59

+0

請注意,問題的標題是錯誤的。你不能改變指針的大小;出於實際的目的,所有數據指針都是相同的大小,而不管它們指向什麼。你可以改變的是指向的對象的大小。如前所述,你可以做些什麼的警告,但如果風是公平的,你可以改變存儲在'uint8_t *'中的值到存儲在'uint64_t *'中的值,然後使用生成的指針在一次操作中獲取64位(8字節)的數據。 – 2015-04-03 23:55:37

+0

好吧,我在typecasts(uint32_t *)中添加了一個*,除了8字節的部分(uint64_t的部分)外,它們現在都在工作。 當我看結果時,它看起來像是被截斷爲一個32位整數而不是一個64位整數。我認爲這是因爲我在打印之前將它作爲'signed int'和'unsigned int'進行轉換。 我應該如何保持64位大小並正確打印它? – user3743206 2015-04-03 23:57:07

回答

2

錯誤的直接來源是您應該使用uint16_t *q = (uint16_t *) p;而不是uint16_t q = (uint16_t) p;,它是指向另一個指針類型的指針類型,然後將其解析。

但是,修改後的代碼依賴於機器結構,存在大/小端和對齊問題。簡而言之,代碼將在x86機器上運行,但可能因未對齊的內存訪問而崩潰,或在其他體系結構上產生錯誤的數字。一種便攜式的方法是這樣的:

uint32_t to_uint32_be(const void* num) 
{ 
    const uint8_t *p = num; 
    uint32_t res = 0U; 
    int i; 
    for (i = 0; i < 4; i++) 
     res = (res << 8) + p[i]; 
    return res; 
} 

在上面的「是」的代碼代表大端,即數據存儲在網絡字節順序最顯著字節。