Да, это стандартное поведение и будет работать во всех компиляторах C.
Вызовы функций всегда выполняются через указатель на функцию:
6.5.22 "Вызовы функций":
Выражение, которое обозначает вызываемую функцию (сноска 77), должно иметь указатель типа на функцию, возвращающую void или возвращающую тип объекта, отличный от типа массива
Как указывает сноска 77, «нормальный» идентификатор функции фактически преобразуется в указатель на функцию, когда используется вызов функции в выражении:
Сноска 77:
Чаще всего это результат преобразования идентификатора, который является указателем функции.
Интересно, что разыменование указателя функции (или указателя функции, преобразованного в указатель функции) дает указатель функции для функции, который будет преобразован обратно в указатель функции для выражения вызова функции. Таким образом, вы можете разыменовать указатель функции (или обычное имя функции), но не обязаны.
6.5.3.2 / 4 «Операторы адреса и косвенности»:
The unary * operator denotes indirection. If the operand points to a function, the result is a function designator
Итак, что касается стандарта, для ваших примеров:
(*fptr)(1,2);
fptr(1,2);
Второе - это не сокращение, а то, что ожидает компилятор. На самом деле, первый пример - это просто более многословный способ сказать то же самое, что и второй. Но некоторые люди могут предпочесть первую форму, поскольку она делает более понятным использование указателя. В сгенерированном коде не должно быть абсолютно никакой разницы.
Другим следствием формулировки стандарта является то, что вы также можете разыменовать имя обычной функции:
func(1,2);
(*func)(1,2); // equivalent to the above
Не то, чтобы на самом деле был какой-то оправданный смысл делать это, о чем я могу думать.