Question

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;
}
Was it helpful?

Solution

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 */

OTHER TIPS

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 chars. 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top