可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Note: This question is about the position of the asterisk (*
).
In most C code I see (e.g., in Beej's guide to network programming), all variable declarations / definitions use the T *name
format, i.e., bind the *
to the variable name. The pointer is thought of belonging to the variable, not the type.
In most C++ code I see, the format is T* name
, i.e., it binds the *
to the type of the variable . The pointer is thought of belonging to the type, not the variable. I myself, as a pure C++ coder, also use this format, as a pointer-to-type clearly (for me) belongs to the type, not the variable. (Incidently, even the C++ standard uses this format in the examples. :) )
Is there a (historic) reason for this? Has the way of thinking just changed when programmers started doing C++?
It would also be nice if a C coder (that uses the former format) could explain on why s/he uses it, and not the latter.
回答1:
From Stroustrup's C++ Style and Technique FAQ.
A "typical C programmer" writes int *p;
and explains it "*p
is what is the int
" emphasizing syntax, and may point to the C (and C++) declaration grammar to argue for the correctness of the style. Indeed, the *
binds to the name p
in the grammar.
A "typical C++ programmer" writes int* p;
and explains it "p
is a pointer to an int
" emphasizing type. Indeed the type of p
is int*
. I clearly prefer that emphasis and see it as important for using the more advanced parts of C++ well.
回答2:
If I were to hazard a guess, I would say it's because C++ people are more likely to consider type information to be a thing in and of itself because templates make it possible to manipulate types programatically at compile time. They are also much less likely to declare several variables in the same declaration.
The T*
style focuses the type information in one place and makes it stand out, and the confusion that would be introduced by something like T* foo, bar;
with this syntax is a non-issue if you never declare two variables in the same statement.
Personally, I find the T*
style to be really obnoxious and dislike it immensely. The *
is part of the type information, it's true, but the way the compiler parses it makes it actually attached to the name, not the type. I think the T*
way obscures something important that's happening.
In my observations, it seems like I'm a rarity in the C++ community. I've noticed the same thing you have about what style is the most popular.
To be clear, of course, either style works in either language. But I do notice the same thing you do, that one style tends to be a bit more common with C code, and the other a bit more common with C++.
回答3:
Personally, I would disagree with this -- I don't think there is a C or C++ way of doing this. I've never seen any evidence to suggest that. However, I do have a hypothesis as to why the syntax with the asterisk closer to the declared variable name in C.
In C (at least, in C89, the vast majority of C in use), you must declare all your variables at the top of a block. This leads to programmers doing
T a, b, c;
relatively often, while in C++ this is rare. (In C++ you declare variables close to where they are used, and variables often have constructor parameters, etc; therefore it's rare to declare multiple objects on a single line)
This also happens to be the only case where the syntax matters, because the statement
T* a, b, c;
declares one pointer, rather than the three the programmer might expect.
Since putting more than one declaration on a single line is more common in C, and also is the only case where the position of the asterisk matters, it's more likely for the programmer to associate the asterisk with the variable.
That said, I've never seen any evidence of this -- this is just conjecture.
回答4:
A couple of people mentioned very good points. I just want to note that while C has kept the meaning "declaration reflects use" very strongly, C++ didn't. Several declarators in C++ don't reflect the use in declarations;
int &ref; // but "&ref" has type "int*", not "int".
int &&ref; // but "&&ref" is not valid at all.
I don't think that C++ programmers writing it different actually have that as their reason, but it may be something stopping C++ book writers from mentioning it, which may influence those C++ programmers.
回答5:
The reason why C programmers tend to use one style while C++ programmers use the other style is quite simple: Kernighan & Ritchie used the "C style" in their book, while Stroustrup used the "C++ style" in his book.
回答6:
In K&R they use the type *name
notation, so may be that's where many C programmers got it.
回答7:
Because Bjarne had the benefit of hindsight: he realized that the C declarator syntax was "an experiment that failed" (read: the C declarator syntax is retarded). The rest has already been answered by others.
回答8:
I don't think you are correct about your distinction,
There's C++ code in the T *
style.
There's C code in the T*
style.
I think it's just a matter of personal preference of the project participants.
回答9:
Just to throw some controversy into the matter:
- C++ users commonly state that one declaration per line makes it okay to put the asterisk on the type (the left).
int* a; int* b;
- Both C and C++ are parsed with the asterisk attached to the name (on the right).
int *a;
- C++ preprocessors often move the asterisk to the left. C preprocessors move it to the right.
- In either language, putting it on the left will look weird for declaring multiple variables of the same type in the same statement.
int* a, * b, * c;
- There are some syntactic elements that look stupid with it on the left.
int* (* func)()
.
There are other elements of C that are incorrectly used, such as const
, which belongs on the right too! int const a;
. This is commonly put on the left of the type, despite belonging to the type to its left. Many compilers have to be modified to handle this usage. In C++ you can observe this is conformed to with constant methods, as the compiler can't deduce for you if it's put on the left: int A::a() const
. This also breaks down with nested usage of const
, restricted
and friends with such declarations as int const *
. Conventional usage of const
would suggest this is a constant pointer to an integer, but that's actually int *const
.
tl;dr
You've all been doing it wrong all along, put everything on the right.
回答10:
C declarations follow the same rules (eg precedence) as expressions. In fact, it's perfectly valid to consider a declaration like
int *foo;
as declaring the type of the expression *foo
(ie the indirection operator applied to foo
) as int
instead of foo
as being of type int*
.
However - as other already pointed out - in C++ its common to think of types as a seperate, and - due to templates - modifyable entity, and thus it makes sense to use a declaration like
int* foo;