Reputation: 1
The code below is an example and the addresses are meant to point to a flash memory of an microcontroller so it wont point to any garbage data.
What I am trying to do is to point the pointer "end_adress" to the end of the memory block. In this case the start of the block is 0x00001000 and end of the block is 0x00002000. I want to set the "end_adress" variable by using the knowledge of the starting address and the size of the memory block.
Is this a good way of solving the problem? Good is in terms of readable code, any other suggestions are mostly welcomed!
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;
}
Upvotes: 0
Views: 596
Reputation: 47593
Your way is almost ok (except the *end_address
) as mentioned in another answer. However, there is still one problem.
Your memory_size
is in bytes, while sizeof
gives a multiple of char
s. sizeof(char)
is always one, but a char may not necessarily be one byte (one example is a TI chip for which I'm coding these days where a char
has two bytes).
Let's see what happens in that case:
/* char is two bytes */
/* sizeof(char) == 1 */
/* sizeof(uint32_t) == 2 */
end_address = start_address + (memory_size/sizeof *end_address);
which translates to:
end_address = (uint32_t *)0x1000 + (0x1000 / 2);
which translates to:
end_address = (uint32_t *)0x1000 + 0x800;
which means 0x800 * 4 bytes after 0x1000, which is 0x3000 (not 0x2000).
What you should do to be sure is use CHAR_BIT
(from limits.h
) that tells how many bytes makes one character. Then do:
end_address = start_address + memory_size / sizeof *end_address / (CHAR_BIT / 8);
assuming CHAR_BIT
is a multiple of 8. If it's not, you would have to know what is the number of bits in a byte and divide by that!
Note that I do / (CHAR_BIT / 8)
(instead of * 8 / CHAR_BIT
) to prevent any possible overflow.
Alternatively, you can write:
end_address = (void *)((char *)start_address + memory_size / (CHAR_BIT / 8));
which may look clearer or more cluttered depending on what you're used to, but is otherwise the same.
Upvotes: 1
Reputation: 14781
To solve your problem, replace this
end_address = start_address + (memory_size/sizeof(end_address));
with:
end_address = start_address + (memory_size/sizeof(*end_address));
Reason: end_address
itself is a pointer while *end_address
is actually the data type that the pointer points to. It would lead to a problem when sizeof(uint32_t) != sizeof(char*)
e.g. on 64-bit or 16-bit systems.
However as you're operating with memory addresses, I would suggest you to use pointers with type char*
so you could do direct arithmetic with it:
char *memory_size = 0x00001000;
uint32_t memory_size = 0x1000;
char *end_address = memory_size + memory_size;
/* then it's assured that end_address == 0x00002000 */
Upvotes: 3