2013-12-11 48 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)); 

这可能看起来更清晰或比较凌乱取决于你使用的是什么,但在其他方面是相同的。