There are two problems here. Two other answers already described the problem with your third call.
But your second call is also incorrect:
char a = 'A'; char b = 'B'; char c = 'C'; char Cptr = *Max(&a, &b, &c);
This should lead to undefined behavior, since strcmp expects a null-terminated string, but this is not what you are passing to the function. Rather, you pass it to pointers to individual char values, and strcmp has every right to strangle it. Basically, anything can happen and that your code works is a pure chance.
The proper way to cause this overload is to simply pass char s or pass C-style strings:
char C = Max(a, b, c); // or: char as[] = "a"; char bs[] = "b"; char cd[] = "c"; char* result = Max(as, bs, cd);
Alternatively, you can directly pass string literals.
Finally, a note about the style. The char* specialization can be greatly reduced if you cheat a bit by converting the input char* strings to the correct std::string and reusing the generic version of Max :
template<> char* Max(char* first,char* second,char* third) { return Max(string(first), string(second), string(third)); }
(Of course, this is probably less effective, but in most cases it can be safely ignored.)
And one more note: the assignment explicitly asked you to specialize the function template for char* so that your answer is correct. However, an alternative would be to overload the function instead of specializing it. For function templates (as opposed to class templates), this is the usual way when you no longer need template arguments:
char* Max(char* first,char* second,char* third) { return Max(string(first), string(second), string(third)); }
Note that the only difference is the absence of template <> before the function header.