Я думаю, если ассемблер данного конкретного контроллера поддерживает постинкремент указателей, и компилятор использует это свойство, то результат будет всегда один.
Нет, это не так. Это только означает что в данном конкретном случае оптимизатору выгоднее было использовать такой набор команд.
Если вдруг окажется, что эта команда находится в цикле со множеством постинкрементных адресаций в пределах одной итерации цикла:
Код
p = &array[0];
do {
i0 = *p++;
...
i1 = *p++;
...
i2 = *p++;
...
i3 = *p++;
} while ();
do {
i0 = *p++;
...
i1 = *p++;
...
i2 = *p++;
...
i3 = *p++;
} while ();
то оптимизирующий компилятор сделает:
Код
p = &array[0] - 4;
do {
LDR R1, [R0, #16]!
...
LDR R2, [R0, #4]
...
LDR R3, [R0, #8]
...
LDR R4, [R0, #12]
} while ();
do {
LDR R1, [R0, #16]!
...
LDR R2, [R0, #4]
...
LDR R3, [R0, #8]
...
LDR R4, [R0, #12]
} while ();
потому что все эти команды внутри цикла в сумме по размеру будут == 4+2+2+2 байт - это меньше, чем:
Код
do {
LDR R1, [R0], #4
...
LDR R2, [R0], #4
...
LDR R3, [R0], #4
...
LDR R4, [R0], #4
} while ();
LDR R1, [R0], #4
...
LDR R2, [R0], #4
...
LDR R3, [R0], #4
...
LDR R4, [R0], #4
} while ();
итого == 4+4+4+4 байт.
В таких случаях выгоднее (в системе команд Cortex-M) сделать один раз приращение указателя в теле цикла, чем в каждой точке *p++.