2013-12-11 3 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 s. sizeof(char) всегда один, но char может не обязательно быть одним байтом (один пример - это чип 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; 

что означает 0x800 * 4 байта после 0x1000, который равен 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)); 

, который может выглядеть яснее и более суматоху в зависимости от того, что вы привыкли, но в остальном то же самое.

Смежные вопросы