Макросы обрабатываются препроцессором - препроцессор выполняет замену текста в исходном файле, заменяя все вхождения 'A' на литерал 8.
Константы обрабатываются компилятором. У них есть дополнительное преимущество - безопасность типов.
Для реального скомпилированного кода с любым современным компилятором не должно быть разницы в производительности между ними.
Определяемые макросом константы заменяются препроцессором. Управление постоянными "переменными" осуществляется так же, как и обычными переменными.
Например, следующий код:
#define A 8
int b = A + 10;
будет выглядеть для реального компилятора как
int b = 8 + 10;
Однако, этот код:
const int A = 8;
int b = A + 10;
будет выглядеть как:
const int A = 8;
int b = A + 10;
:)
На практике, главное, что меняется - это область видимости: постоянные переменные подчиняются тем же правилам области видимости, что и стандартные переменные в C, что означает, что они могут быть ограничены, или, возможно, переопределены, в пределах определенного блока, без утечки информации - это похоже на ситуацию с локальными и глобальными переменными.
В C вы можете написать
#define A 8
int arr[A];
но не:
const int A = 8;
int arr[A];
если я правильно помню правила. Обратите внимание, что на C++ оба варианта будут работать.
Во-первых, первое заставит препроцессор заменить все вхождения A на 8 до того, как компилятор что-либо сделает, тогда как второй не задействует препроцессор