2015-11-03 31 views
5

假設我有一個uint8_t指針指向數組中的第三個元素{1,2,4,5},因此*p是4.我怎樣才能讓它指向點到4和5,所以*p是45.這是可能的嗎?我目前正在類型化。這是我做的事情,例如如果數據是我的數組{1,2,4,5},我想4和5如何使指針指向兩個或多個連續的單元格

uint8_t dummyAddress = data[2]; 
dummyAddress = *((uint16_t*) dummyAddress); 
*p = *dummyAddress; 

我的理解是,P中就應指向4和5,但我不是。相反,當我執行第二行時,我會遇到seg錯誤。 p是uint64_t * const。它的工作原理是獲得一個字節,但是當將相同的邏輯應用於兩個字節時,我沒有得到正確的結果。

+0

請給出完整的代碼(數組聲明,所用變量的類型,...)。 –

+0

您應該使用更高的警告級別編譯並收聽編譯器警告。 –

+1

在你的代碼中'dummyAddress'不是一個指針 –

回答

4

你可以這樣做:

uint8_t data[] = { 1, 2, 4, 5 }; 
uint8_t *p8 = &data[2]; 
uint16_t u16 = *(uint16_t*)p8; 

然後(uint16_t*)p8將指向data[2]data[3]。但你不能輕易訪問*(uint16_t*)p8。首先這是因爲p8可能不會在uint16_t邊界上對齊。在這種情況下,某些處理器會導致異常。其次,即使您可以訪問*(uint16_t*)p8,根據處理器的字節順序(大端/小端),您可能會得到不同的結果。你可能會得到0x0405,或者你可能會得到0x0504。

還請注意,您在行

dummyAddress = *((uint16_t*) dummyAddress); 

你第一次重新詮釋dummyAddress爲指針,以uint16_t,然後提領,所以返回uint16_tdummyAddress存儲這一點。這顯然不是你想要做的。如果真的編譯好了,請考慮用更高的警告級別進行編譯,並查看每個編譯器的警告(只有在瞭解它並確信它不是編程錯誤的情況下才會忽略它)。

順便說一句,您將無法獲得指針p,其中*p==45正如您在您的問題中請求的那樣。

而且,MCH說:What is the strict aliasing rule?

+0

默認它看起來像是抓住小端的字節,所以* p是0x0504。現在如果我想反轉它,所以* p讀取0x405我很困惑如何去做。我見過有人使用<<運算符並將位移動8次或乘以256倍特定次數?任何解釋請 – ponderingdev

+1

是的,你可以這樣做,像'uint16_t a = ...; uint16_t b =(a >> 8)| (a << 8)'。甚至更好直接在數據數組上運行uint16_t b =((uint16_t)data [2] << 8)|數據[3]'(或交換數據[2]和數據[3])。 –

0

你應該寫:

uint_8_t *dummyAddress= &data[2]; 
uint_16_t *dummyAddress2= (uint16_t *) dummyAddress; 

uint_16_t p= *dummyAddress2; 

但要注意的是,由於「字節序」,你可能會得到兩個uint_8的順序錯誤,即作爲{data[3], data[2}

+2

,它是未定義的行爲,因爲它違反了嚴格的別名規則。 – mch

1

如果我明白你在做什麼,那麼是的,你可以通過鑄造到uint16_t來訪問這兩個字節,但是你會遇到問題(或者字節順序問題),以及字節存儲在內存中的順序以及違反嚴格走樣。這可能會返回一個你沒有懷疑的答案。例如:

#include <stdio.h> 
#include <stdint.h> 

int main (void) { 

    uint8_t array[] = {1,2,3,4}; 
    uint8_t *p = array + 2; 

    printf ("\n the uint8_t answer : %hhd\n", *p); 
    printf (" the uint16_t answer : %hd\n\n", *(uint16_t *)p); 

    printf ("**note: the will cast result in bytes 4, 3" 
      " (or (4 << 8 | 3) = 1027)\n\n"); 

    return 0; 
} 

輸出

$ ./bin/cast_array 

the uint8_t answer : 3 
the uint16_t answer : 1027 

**note: the cast will result in bytes 4, 3 (or (4 << 8 | 3) = 1027) 

的字節被存儲在存儲器中在我的系統中little endian順序。因此,當您投射到uint16_t時,它期望找到least significant,most significant字節。在上面的示例中,在內存中使用34時,演員會將實際訂單解釋爲43,導致值爲1027而不是(3 << 8) | 4 = 772

正如指出的那樣,你將通過轉換成比char結果不確定的行爲以外的任何違反有關嚴格別名哪裏型修剪規則。所有這些行爲的結果都依賴於硬件和編譯器,除了學習練習之外,不應該用於其他任何事情。

+0

'*(uint16_t *)p'調用未定義的行爲,因爲它違反了嚴格的別名規則。 – mch

+0

是的,我會放下關於修剪類型的說明。 –

相關問題