有没有一种“好”的方法可以在 C/C++ 中编写“指向某物的指针”?
我以前写void foo( char *str );
但有时我觉得它很不合逻辑,因为类型str
是“指向char的指针”,那么将它附加*
到类型名称应该更合乎逻辑。
有写指针的规则吗?
char*str;
char* str;
char *str;
char * str;
有没有一种“好”的方法可以在 C/C++ 中编写“指向某物的指针”?
我以前写void foo( char *str );
但有时我觉得它很不合逻辑,因为类型str
是“指向char的指针”,那么将它附加*
到类型名称应该更合乎逻辑。
有写指针的规则吗?
char*str;
char* str;
char *str;
char * str;
没有严格的规则,但请记住*
附加到变量,所以:
char *str1, *str2; // str1 and str2 are pointers
char* str1, str2; // str1 is a pointer, str2 is a char
有些人也喜欢这样做char * str1
,但这取决于您或您公司的编码标准。
常见的 C 约定是写T *p
,而常见的 C++ 约定是写T* p
。两者都解析为T (*p)
; 这*
是声明符的一部分,而不是类型说明符。这纯粹是指针声明语法的意外,您可以用任何一种方式编写它。
C(以及扩展的 C++)声明语法是以表达式为中心的;IOW,声明的形式应该与代码中相同类型的表达式的形式相匹配。
例如,假设我们有一个指向 的指针int
,并且我们想要访问该整数值。为此,我们使用间接运算符取消引用指针,如下所示:*
x = *p;
表达式 的类型*p
是int
; 因此,因此声明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])
float
float
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
约定,声明f
为arrptrfunc* f
. 我个人不喜欢以这种方式做事,因为从 typedef 中不一定清楚f
应该如何在表达式中使用,或者如何使用 type 的对象arrptrfunc
。非 typedef 的版本可能很难看且难以阅读,但至少它会预先告诉您需要了解的所有内容;你不必去挖掘所有的typedef。
“好方法”取决于
(可能)按这个顺序。
这没有对错之分。重要的是选择一种编码标准并坚持下去。
话虽如此,我个人认为 * 属于类型而不是变量名,因为类型是“指向 char 的指针”。变量名不是指针。
我认为这将受到声明变量的一般模式的严重影响。
例如,我倾向于每行只声明一个变量。这样,我可以添加一条注释来提醒我如何使用该变量。
但是,有时在一行中声明多个相同类型的变量是可行的。在这种情况下,我个人的编码规则是永远,永远,永远在同一行声明指针作为非指针。我发现混合它们可能是错误的来源,所以我尝试通过避免混合来更容易地看到“错误”。
只要我遵循第一个准则,我发现只要我是一致的,我如何声明指针并不重要。
但是,如果我使用第二个准则并在同一行声明多个指针,我发现以下样式是最有益和最清晰的(当然其他人可能不同意)...
char *ptr1, *ptr2, *ptr3;
通过在 * 和指针名称之间没有空格,更容易发现我是否违反了第二条准则。
现在,如果我想在我的两个个人风格指南之间保持一致,当在一行上只声明一个指针时,我会使用 ...
char *ptr;
无论如何,这就是我为什么要做我所做的部分原因。希望这可以帮助。