在C / C ++中编写“指向某事物的指针”的好方法

时间:2011-02-16 11:58:36

标签: c++ c pointers typography

在C / C ++中编写“指向某事物的指针”是否有“好”的方法? 我用来写void foo( char *str );但有时我发现它非常不合逻辑,因为str的类型是“指向char的指针”,那么将*附加到类型名称更合乎逻辑。
是否有编写指针的规则?

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

5 个答案:

答案 0 :(得分:21)

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

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

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

答案 1 :(得分:9)

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

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

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

x = *p; 

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

int *p  

p的内容由类型说明符int提供,但p的指针由声明符*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的类型是“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。

答案 2 :(得分:3)

“好方法”取决于

  1. 项目中的内部编码标准
  2. 您的个人偏好
  3. (可能)按此顺序。

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

我认为这会受到人们如何宣布变量的一般模式的影响。

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

然而,有时候,在一行上声明几个相同类型的变量是可行的。在这种情况下,我的个人编码规则永远不会在与非指针相同的行上声明指针。我发现混合它们可能是错误的来源,所以我试图通过避免混合来更容易看到“错误”。

只要遵循第一条准则,我发现只要我保持一致,我就会如何声明指针并不重要。

但是,如果我使用第二条准则并在同一条线上声明几个指针,我发现以下风格最有益和明确(当然其他人可能不同意)......

char  *ptr1, *ptr2, *ptr3;

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

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

char  *ptr;

无论如何,这是我为什么做我做的部分原因。希望这会有所帮助。