问题
Is there a "good" way to write "pointer to something" in C/C++ ?
I use to write void foo( char *str );
But sometimes I find it quite illogical because the type of str
is "pointer to char", then it should more logical to attach the *
to the type name.
Is there a rule to write pointers ?
char*str;
char* str;
char *str;
char * str;
回答1:
The common C convention is to write T *p
, whereas the common C++ convention is to write T* p
. Both parse as T (*p)
; the *
is part of the declarator, not the type specifier. It's purely an accident of pointer declaration syntax that you can write it either way.
C (and by extension, C++) declaration syntax is expression-centric; IOW, the form of a declaration should match the form of an expression of the same type in the code.
For example, suppose we had a pointer to int
, and we wanted to access that integer value. To do so, we dereference the pointer with the *
indirection operator, like so:
x = *p;
The type of the expression *p
is int
; thus, it follows that the declaration of p
should be
int *p
The int-ness of p
is provided by the type specifier int
, but the pointer-ness of p
is provided by the declarator *p
.
As a slightly more complicated example, suppose we had a pointer to an array of float
, and wanted to access the floating point value at the i
'th element of the array through the pointer. We dereference the array pointer and subscript the result:
f = (*ap)[i];
The type of the expression (*ap)[i]
is float
, so it follows that the declaration of the array pointer is
float (*ap)[N];
The float-ness of ap
is provided by the type specifier float
, but the pointer-ness and array-ness are provided by the declarator (*ap)[N]
. Note that in this case the *
must explicitly be bound to the identifer; []
has a higher precedence than unary *
in both expression and declaration syntax, so float* ap[N]
would be parsed as float *(ap[N])
, or "array of pointers to float
", rather than "pointer to array of float
". I suppose you could write that as
float(* ap)[N];
but I'm not sure what the point would be; it doesn't make the type of ap
any clearer.
Even better, how about a pointer to a function that returns a pointer to an array of pointer to int
:
int *(*(*f)())[N];
Again, at least two of the *
operators must explicitly be bound in the declarator; binding the last *
to the type specifier, as in
int* (*(*f)())[N];
just indicates confused thinking IMO.
Even though I use it in my own C++ code, and even though I understand why it became popular, the problem I have with the reasoning behind the T* p
convention is that it just doesn't apply outside of the simplest of pointer declarations, and it reinforces a simplistic-to-the-point-of-being-wrong view of C and C++ declaration syntax. Yes, the type of p
is "pointer to T", but that doesn't change the fact that as far as the language grammar is concerned *
binds to the declarator, not the type specifier.
For another case, if the type of a
is "N-element array of T", we don't write
T[N] a;
Obviously, the grammar doesn't allow it. Again, the argument just doesn't apply in this case.
EDIT
As Steve points out in the comments, you can use typedefs to hide some of the complexity. For example, you could rewrite
int *(*(*f)())[N];
as something like
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
Now you can cleanly apply the T* p
convention, declaring f
as arrptrfunc* f
. I personally am not fond of doing things this way, since it's not necessarily clear from the typedef how f
is supposed to be used in an expression, or how to use an object of type arrptrfunc
. The non-typedef'd version may be ugly and difficult to read, but at least it tells you everything you need to know up front; you don't have to go digging through all the typedefs.
回答2:
There is no strict rule, but bear in mind that the *
attaches to the variable, so:
char *str1, *str2; // str1 and str2 are pointers
char* str1, str2; // str1 is a pointer, str2 is a char
Some people like to do char * str1
as well, but it's up to you or your company's coding standard.
回答3:
The "good way" depends on
- internal coding standards in your project
- your personal preferences
(probably) in that order.
回答4:
There is no right or wrong in this. The important thing is to pick one coding standard and stick to it.
That being said, I personally believe that the * belongs with the type and not the variable name, as the type is "pointer to char". The variable name is not a pointer.
回答5:
I think this is going to be heavily influenced by the general pattern in how one declares the variables.
For example, I have a tendency to declare only one variable per line. This way, I can add a comment reminding me how the variable is to be used.
However, there are times, when it is practical to declare several variables of the same type on one line. Under such circumstances, my personal coding rule is to never, NEVER, EVER declare pointers on the same line as non-pointers. I find that mixing them can be a source of errors, so I try to make it easier to see "wrongness" by avoiding mixing.
As long as I follow the first guideline, I find that it does not matter overly much how I declare the pointers so long as I am consistent.
However, if I use the second guideline and declare several pointers on the same line, I find the following style to be most beneficial and clear (of course others may disagree) ...
char *ptr1, *ptr2, *ptr3;
By having no space between the * and the pointer name, it becomes easier to spot whether I have violated the second guideline.
Now, if I wanted to be consistent between my two personal style guidelines, when declaring only one pointer on a line, I would use ...
char *ptr;
Anyway, that's my rationale for part of why I do what I do. Hope this helps.
来源:https://stackoverflow.com/questions/5016117/good-way-to-write-pointer-to-something-in-c-c