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