Czyli jak pojawi sie symbol ten co już był to koniec i własnie ten symbol jest tym finalnym zastąpnikiem?
Tak, preprocesor nie dopuszcza rekurencji (chociaż tego wprost nikt nigdy nie napisał w standardach C/C++).
A czemu dla y,z powyższy kod się kompiluje, a jak dodam deklarację int a to już niestety nie chce się skompilować, bo mówi że redefinicja? To dlaczego nie mówi że dla y jest redefinicja albo dla y i z?
Dlatego, że wynikiem pierwszej definicji zmiennych są zmienne widziane przez kompilator jako 'a' i 'y' - co doskonale widać na tym co podałem w poprzednich postach i rozpisałem potem.
W drugiej linii zachodzi postawienie 'a' -> 'y', potem 'y' -> 'a', na tym się kończy. Dlaczego wypluwa redefinicję? Zobacz, że 'z' przechodzi w 'a', potem zachodzi proces dla 'a', czyli w praktyce jakby tam od początku było 'a', które będzie przez preprocesor mielone. Jeszcze raz rozpisane, może czytelniej:
#define z a
#define y a
#define a y
[z] z -> a -> y -> a
[y] y -> a -> y
[a] a -> y -> a
Czyli na wyjściu preprocesora i 'z' i 'a' są przetłumaczone do 'a', dlatego kompilator stwierdza, że już taka zmienna przecież istnieje.