Fra*_*ger 3 c c++ pointers typography
在C/C++中编写"指向某事物的指针"是否有"好"的方法?
我用来写void foo( char *str );但有时我发现它非常不合逻辑,因为类型str是"指向char的指针",那么它应该更合乎逻辑地附加*到类型名称.
写指针有规则吗?
char*str;
char* str;
char *str;
char * str;
Run Code Online (Sandbox Code Playgroud)
DrA*_*rAl 22
没有严格的规则,但请记住*附加到变量,所以:
char *str1, *str2; // str1 and str2 are pointers
char* str1, str2; // str1 is a pointer, str2 is a char
Run Code Online (Sandbox Code Playgroud)
有些人喜欢这样做char * str1,但这取决于您或您公司的编码标准.
常见的C约定是写入T *p,而常见的C++约定是写入T* p.两者都解析为T (*p); 它*是声明符的一部分,而不是类型说明符.这纯粹是指针声明语法的一个意外,你可以用它来编写它.
C(以及扩展,C++)声明语法是以表达为中心的 ; IOW,声明的形式应该与代码中相同类型的表达式的形式相匹配.
例如,假设我们有一个指针int,我们想访问该整数值.为此,我们使用间接运算符取消引用指针*,如下所示:
x = *p;
Run Code Online (Sandbox Code Playgroud)
表达式 的类型*p是int; 因此,p应该声明
int *p
Run Code Online (Sandbox Code Playgroud)
int-ness p是由类型说明符提供的int,但指针式p是由声明符提供的*p.
作为一个稍微复杂的例子,假设我们有一个指向数组的指针float,并希望i通过指针访问数组的第th个元素的浮点值.我们取消引用数组指针并下标结果:
f = (*ap)[i];
Run Code Online (Sandbox Code Playgroud)
表达式 的类型(*ap)[i]是float,所以它遵循数组指针的声明
float (*ap)[N];
Run Code Online (Sandbox Code Playgroud)
float-ness ap是由类型说明符提供的float,但指针-ness和array-ness由声明符提供(*ap)[N].请注意,在这种情况下,*必须明确地绑定到标识符; []具有比一元的优先级高*的表达和声明的语法,所以float* ap[N]将被解析为float *(ap[N]),或"指针数组float",而不是"指针的数组float".我想你可以把它写成
float(* ap)[N];
Run Code Online (Sandbox Code Playgroud)
但我不确定这是什么意思; 它没有ap任何更清晰的类型.
更好的是,指向函数的指针如何返回指向指针数组的指针int:
int *(*(*f)())[N];
Run Code Online (Sandbox Code Playgroud)
同样,至少有两个*运算符必须在声明符中明确绑定; 将最后一个绑定*到类型说明符,如
int* (*(*f)())[N];
Run Code Online (Sandbox Code Playgroud)
只是表明IMO思维混乱.
即使我在自己的C++代码中使用它,即使我理解为什么它变得流行,我对T* p公约背后的推理的问题是它只是不适用于最简单的指针声明之外,它强化了C和C++声明语法的简单到错误的观点.是的,类型p是"指向T的指针",但这并没有改变这样一个事实,即语言语法*与声明符绑定,而不是类型说明符.
对于另一种情况,如果类型a是"N元素数组T",我们不写
T[N] a;
Run Code Online (Sandbox Code Playgroud)
显然,语法不允许它.同样,这个论点在这种情况下并不适用.
编辑
正如Steve在评论中指出的那样,你可以使用typedef隐藏一些复杂性.例如,您可以重写
int *(*(*f)())[N];
Run Code Online (Sandbox Code Playgroud)
就像这样
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
Run Code Online (Sandbox Code Playgroud)
现在你可以干净地应用T* p约定,声明f为arrptrfunc* f.我个人并不喜欢用这种方式做事,因为从typedef中不一定清楚如何f在表达式中使用它,或者如何使用类型的对象arrptrfunc.非typedef'd版本可能很丑陋且难以阅读,但至少它告诉你需要事先了解的所有内容; 你不必去挖掘所有的typedef.