3

有没有一种“好”的方法可以在 C/C++ 中编写“指向某物的指针”?
我以前写void foo( char *str );但有时我觉得它很不合逻辑,因为类型str是“指向char的指针”,那么将它附加*到类型名称应该更合乎逻辑。
有写指针的规则吗?

char*str;
char* str;
char *str;
char * str;
4

5 回答 5

21

没有严格的规则,但请记住*附加到变量,所以:

char *str1, *str2; // str1 and str2 are pointers
char* str1, str2;  // str1 is a pointer, str2 is a char

有些人也喜欢这样做char * str1,但这取决于您或您公司的编码标准。

于 2011-02-16T12:01:05.680 回答
8

常见的 C 约定是写T *p,而常见的 C++ 约定是写T* p。两者都解析为T (*p); 这*是声明符的一部分,而不是类型说明符。这纯粹是指针声明语法的意外,您可以用任何一种方式编写它。

C(以及扩展的 C++)声明语法是以表达式为中心的;IOW,声明的形式应该与代码中相同类型的表达式的形式相匹配。

例如,假设我们有一个指向 的指针int,并且我们想要访问该整数值。为此,我们使用间接运算符取消引用指针,如下所示:*

x = *p; 

表达式 的类型*pint; 因此,因此声明p应该是

int *p  

的 int-nessp由类型说明符 提供int,但指针 的p由 declarator 提供*p

作为一个稍微复杂一点的例子,假设我们有一个指向数组的指针,并且想要通过指针访问数组第 ' 个元素float处的浮点值。i我们取消引用数组指针并为结果下标:

f = (*ap)[i];

表达式 的类型(*ap)[i]float,因此数组指针的声明是

float (*ap)[N];

的浮点数ap由类型说明符提供float,但指针和数组由声明符提供(*ap)[N]。请注意,在这种情况下,*必须明确绑定到标识符;在表达式和声明语法中[]具有比一元更高的优先级,因此将被解析为,或“指向数组的指针”,而不是“指向数组的指针”。我想你可以写成*float* ap[N]float *(ap[N])floatfloat

float(* ap)[N];

但我不确定重点是什么;它不会使类型ap更清晰。

更好的是,一个指向函数的指针如何返回指向指针数组的指针int

int *(*(*f)())[N];

同样,至少有两个*运算符必须在声明器中显式绑定;将最后一个绑定*到类型说明符,如

int* (*(*f)())[N];

只是表示思维混乱的IMO。

即使我在我自己的 C++ 代码中使用它,即使我理解它为什么变得流行,我对T* p约定背后的推理的问题是它只是不适用于最简单的指针声明之外,它强化了C 和 C++ 声明语法的简单化错误观点。是的,类型p是“指向 T 的指针”,但这并没有改变这样一个事实,即就语言语法而言,它*绑定到声明符,而不是类型说明符。

另一种情况,如果类型a是“T的N元素数组”,我们

T[N] a;

显然,语法不允许。同样,该论点不适用于这种情况。

编辑

正如史蒂夫在评论中指出的那样,您可以使用 typedef 来隐藏一些复杂性。例如,您可以重写

int *(*(*f)())[N];

就像

typedef int *iptrarr[N];           // iptrarr is an array of pointer to int
typedef iptrarr *arrptrfunc();     // arrptrfunc is a function returning
                                   // a pointer to iptrarr

arrptrfunc *f;                     // f is a pointer to arrptrfunc

现在您可以干净地应用T* p约定,声明farrptrfunc* f. 我个人不喜欢以这种方式做事,因为从 typedef 中不一定清楚f应该如何在表达式中使用,或者如何使用 type 的对象arrptrfunc。非 typedef 的版本可能很难看且难以阅读,但至少它会预先告诉您需要了解的所有内容;你不必去挖掘所有的typedef。

于 2011-02-16T15:59:17.107 回答
3

“好方法”取决于

  1. 项目中的内部编码标准
  2. 您的个人喜好

(可能)按这个顺序。

于 2011-02-16T12:14:05.850 回答
1

这没有对错之分。重要的是选择一种编码标准并坚持下去。

话虽如此,我个人认为 * 属于类型而不是变量名,因为类型是“指向 char 的指针”。变量名不是指针。

于 2011-02-16T14:09:51.717 回答
0

我认为这将受到声明变量的一般模式的严重影响。

例如,我倾向于每行只声明一个变量。这样,我可以添加一条注释来提醒我如何使用该变量。

但是,有时在一行中声明多个相同类型的变量是可行的。在这种情况下,我个人的编码规则是永远,永远,永远在同一行声明指针作为非指针。我发现混合它们可能是错误的来源,所以我尝试通过避免混合来更容易地看到“错误”。

只要我遵循第一个准则,我发现只要我是一致的,我如何声明指针并不重要。

但是,如果我使用第二个准则并在同一行声明多个指针,我发现以下样式是最有益和最清晰的(当然其他人可能不同意)...

char  *ptr1, *ptr2, *ptr3;

通过在 * 和指针名称之间没有空格,更容易发现我是否违反了第二条准则。

现在,如果我想在我的两个个人风格指南之间保持一致,当在一行上只声明一个指针时,我会使用 ...

char  *ptr;

无论如何,这就是我为什么要做我所做的部分原因。希望这可以帮助。

于 2011-02-16T12:30:20.723 回答