2013-12-11 85 views
0

下面的代碼是一個例子,地址是指微控制器的閃存,所以它不會指向任何垃圾數據。增加一個固定值的指針

我想要做的是將指針「end_adress」指向內存塊的末尾。在這種情況下,塊的起始位是0x00001000,塊的末尾是0x00002000。我想通過使用內存塊的起始地址和大小的知識來設置「end_adress」變量。

這是解決問題的好方法嗎? 好的是在可讀的代碼方面,其他的建議大多是歡迎的!

static const uint32_t memory_size = 0x00001000; 
static volatile const uint32_t* start_address = (volatile const uint32_t*)0x00001000; 
static volatile uint32_t* end_address; 

int main(int argc, char *argv[]) 
{ 
    end_address = start_address + (memory_size/sizeof(end_address)); 
    printf("End adress: %x \n", end_address); 

    return 0; 
} 

回答

3

解決您的問題,更換此

end_address = start_address + (memory_size/sizeof(end_address)); 

有:

end_address = start_address + (memory_size/sizeof(*end_address)); 

原因:end_address本身是一個指針,而*end_address實際上是數據類型的指針指向。當例如sizeof(uint32_t) != sizeof(char*)例如這會導致問題。在64位或16位系統上。

但是,你正在使用的內存地址的操作,我建議你使用指針與char*類型,所以你可以直接做算術吧:

char *memory_size = 0x00001000; 
uint32_t memory_size = 0x1000; 
char *end_address = memory_size + memory_size; 
/* then it's assured that end_address == 0x00002000 */ 
+2

使用'char *'而不是'void *'。算術在'void *'上不起作用(除非編譯器允許它作爲語言擴展)。 –

+0

@MichaelBurr非常感謝您指出這一點。 :) – starrify

1

你的方式幾乎是確定(除*end_address)正如另一個答案中提到的。不過還有還有一個問題。

memory_size字節,而sizeof給出char小號的倍數。 sizeof(char)始終爲1,但字符不一定是一個字節(一個示例是我現在編碼的TI芯片,其中char有兩個字節)。

讓我們來看看在這種情況下會發生什麼:

/* char is two bytes */ 
/* sizeof(char) == 1 */ 
/* sizeof(uint32_t) == 2 */ 
end_address = start_address + (memory_size/sizeof *end_address); 

翻譯爲:

end_address = (uint32_t *)0x1000 + (0x1000/2); 

翻譯爲:

end_address = (uint32_t *)0x1000 + 0x800; 

這爲0x1000後,意味着將0x800 * 4個字節,它是0x3000(不是0x2000)。

你應該怎麼做才能確定是使用CHAR_BIT(來自limits.h),它告訴一個字符有多少個字節。然後做:

end_address = start_address + memory_size/sizeof *end_address/(CHAR_BIT/8); 

假設CHAR_BIT是8的倍數。如果不是的話,你會知道什麼是由一個字節和除法的位數!

請注意,我做/ (CHAR_BIT/8)(而不是* 8/CHAR_BIT)以防止任何可能的溢出。


或者,你可以寫:

end_address = (void *)((char *)start_address + memory_size/(CHAR_BIT/8)); 

這可能看起來更清晰或比較凌亂取決於你使用的是什麼,但在其他方面是相同的。