Фактически нет никакой разницы; объявление анализируется , как если бы было написано float (*varname);
.
В C и C ++ объявления сосредоточены вокруг выражений , а не объектов; в основном, форма объявления должна соответствовать форме выражения в исполняемом коде (IOW, объявление имитирует использование). Например, если у вас есть указатель на целое число с именем p
и вы хотите получить доступ к этому целому числу значению , на которое указывает p
, вы разыменовываете указатель следующим образом:
x = *p;
Тип выражения *p
является целым; таким образом, объявление должно выглядеть как
int *p;
Аналогично, если у вас есть массив int с именем arr
и вы хотите получить доступ к целочисленному значению в конкретном элементе i
, вы должны написать
x = a[i];
Тип выражения a[i]
является целым; таким образом, объявление должно выглядеть как
int a[N];
В приведенных выше примерах *p
и a[N]
называются деклараторами ; объявители вводят имя объявляемого объекта вместе с дополнительной информацией о типе, не предоставленной в спецификаторе типа . Целочисленность p
и a
обеспечивается спецификатором типа int
, но указатель p
и массив a
обеспечиваются их соответствующими деклараторами .
Это важный момент, который нужно подчеркнуть; *
как int *p;
, так и int* p;
привязаны к декларатору , а не к спецификатору типа, независимо от пробелов. Тот факт, что вы можете написать это в любом случае, является случайностью синтаксиса C (и C ++), и в результате есть школа мысли, что переменные-указатели должны быть объявлены как T* p;
, а не T *p;
, так как type из p
- это «указатель на T». Моя проблема в том, что рассуждения only работают для простых типов указателей; мы не можем обращаться с массивами или типами функций одинаково. Например, мы не можем записать int[N] arr;
, даже если тип из arr
равен «N-элементному массиву int». Это действительно падает, когда мы начинаем объявлять указатели на массивы, или указатели на функции, или их комбинации. Например:
int *(*(*(*farr)())[N])();
Тип из farr
- это «указатель на функцию, возвращающую указатель на N-элементный массив указателей на функции, возвращающие указатели на int». Все, кроме «int», является частью объявления; писать int* (*(*(*farr)())[N])();
или даже int*(*(*(* farr)())[N])();
было бы просто ... глупо.
Я считаю, что настаивание на написании T* p;
для объявлений указателей приводит к большей путанице, а не к меньшей. Как бы Stroustrup и легионы программистов C ++ не хотели делать вид, иначе, объявления в C и C ++ сосредоточены вокруг выражений , а не объектов.
Поскольку я являюсь частью большой команды, пишущей код на C ++, я следую согласованным рекомендациям по кодированию, которые включают объявление указателя и ссылок как T* p;
и T& r;
, но это заставляет меня скрипеть зубами каждый раз, когда у меня есть сделать это.