In your post you state: When I execute the program I expect the address to be 0Xffc10004
But then you start off with:
uint32_t *a = (uint32_t *)0xFFC10004;
Did you mean uint32_t *a = (uint32_t *)0xFFC10000; ?
Based on the assumption of a typo in your code segment the following will use (uint32_t *)0xFFC10000.
But first Keep in mind that the value 0x40 is not the same as 0x4
    0x40; == 64
    0x4;  == 4 (use this one if you want to see a 4 byte change) 
When incrementing a pointer type, the distance from one location to the next sequential location is always sizeof(type). For example:
a + 1 == a + sizeof(uint32_t)
a + 0x40 == a + 0x40*sizeof(uint32_t)
etc.
This will illustrate:
uint32_t *p = (uint32_t *)0xFFC10000;//starting with value intended in post (not 0xFFC10000)
printf("base location: \t\t%p\n", p);    // base location of p
printf("base location + 0x4:\t%p\t(%p + 0x4*sizeof(uint32_t))\n", p+0x4, p);    // adds 4*sizeof(uint32_t) to base location  of p
printf("base location + 0x40:\t%p\t(%p + 0x40*sizeof(uint32_t))\n", p+0x40, p); // adds 0x40*sizeof(uint32_t) to base location  of p
printf("base location + 1:\t%p\t(%p + sizeof(uint32_t))\n", p+0x1, p);          // adds 1*sizeof(uint32_t) to base location of p
Outputs the values as indicated above:
