Ответ 1
Сначала компилятор выбирает первичный шаблон и только затем определяет, какую специализацию использовать. То есть в вашем случае компилятор всегда выбирает второй первичный шаблон, т.е. # 3.
Однако, поскольку вы не указали аргумент шаблона при специализировании шаблона функции, ваша специализация специализируется на различном основном шаблоне в зависимости от его местоположения: с заданным порядком он специализируется на первом основном шаблоне, когда вы обмениваете порядок # 2 и # 3 он специализируется на втором основном шаблоне. В пункте 14.7.3 [temp.expl.spec] стандарт должен сказать следующее о ситуации
... При написании специализации будьте осторожны с ее местоположением; или сделать его компиляцией, станет таким испытанием, чтобы разжечь его самосожжение.
Если вы хотите контролировать, какой первичный шаблон специализация действительно специализируется, вы должны указать аргументы шаблона в специализации:
template <> void c<int*>(int* in) { ... } // specializes the first primary
template <> void c<int>(int* in) { ... } // specializes the second primary