阅读复杂的 const 声明的简单规则?
要读取复杂的指针声明,有
但这条规则没有提到如何读取const
修饰符。
例如,在简单的指针声明中,const
可以通过多种方式应用:
char *buffer; // non-const pointer to non-const memory
const char *buffer; // non-const pointer to const memory
char const *buffer; // equivalent to previous declartion
char * const buffer = {0}; // const pointer to non-const memory
char * buffer const = {0}; // error
const char * const buffer = {0}; // const pointer to const memory
现在将 const
与指针声明的指针一起使用怎么样?
char **x; // no const;
const char **x;
char * const *x;
char * * const x;
const char * const * x;
const char * * const x;
const char * const * const x;
阅读这些声明的简单规则是什么? 哪些声明有意义?
顺时针/螺旋规则适用吗?
两个真实世界的示例
方法 ASTUnit::LoadFromCommandLine
使用 const char **
提供命令行参数(在 llvm clang 中 来源)。
getopt()
的自变量向量参数声明如下:
int getopt(int argc, char * const argv[], const char *optstring);
其中 char * const argv[]
相当于该上下文中的 char * const * argv
。
由于这两个函数使用相同的概念(指向字符串的指针向量来提供参数)并且声明不同 - 明显的问题是:为什么它们不同?其中一个比另一个更有意义吗?
意图应该是:const
修饰符应指定该函数不操作此向量的字符串,并且不更改向量的结构。
For reading complex pointer declarations there is the right-left rule.
But this rule does not mention how to read const
modifiers.
For example in a simple pointer declaration, const
can be applied in several ways:
char *buffer; // non-const pointer to non-const memory
const char *buffer; // non-const pointer to const memory
char const *buffer; // equivalent to previous declartion
char * const buffer = {0}; // const pointer to non-const memory
char * buffer const = {0}; // error
const char * const buffer = {0}; // const pointer to const memory
Now what about the use of const
with a pointer of pointer declaration?
char **x; // no const;
const char **x;
char * const *x;
char * * const x;
const char * const * x;
const char * * const x;
const char * const * const x;
And what is an easy rule to read those declarations?
Which declarations make sense?
Is the Clockwise/Spiral Rule applicable?
Two real world examples
The method ASTUnit::LoadFromCommandLine
uses const char **
to supply command line arguments (in the llvm clang source).
The argument vector parameter of getopt()
is declared like this:
int getopt(int argc, char * const argv[], const char *optstring);
Where char * const argv[]
is equivalent to char * const * argv
in that context.
Since both functions use the same concept (a vector of pointers to strings to supply the arguments) and the declarations differ - the obvious questions are: Why do they differ? Makes one more sense than the other?
The intend should be: The const
modifier should specify that the function does not manipulate strings of this vector and does not change the structure of the vector.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
(试图关注问题的其他方面)
const 的经验法则声明是从右到左读取它们,
const
修改下一个标记。例外:在声明的开头const
修改前一个标记。此异常背后有一个 基本原理 - 对于基本声明
const char c
对某些人来说比 char const c 更自然 - 据报道,const char c
的前体形式早于最终的 const 规则。getopt
或
这意味着 argv 是一个指向 const 向量的指针,该向量由指向非常量字符串的指针组成。
但是人们会期望以下声明:(
指向 const 向量的指针到 const 字符串)
因为 getopt() 不应该更改通过 argv 引用的字符串。
至少
char **
(如main()
中使用的)会自动转换为char * const * argv
。Clang
这意味着 argv 是一个指向 const 字符串指针的非常量数组的指针。
同样,出于与上述相同的原因,人们会期望
const char * const *argv
。但这更引人注目,因为
char **
不转换为const char **
,例如产生编译错误,而
和 则
不会。
(Trying to focus on other aspects of the question)
The rule of thumb for const declarations is to read them from right to left and
const
modifies the next token. Exception: At the beginning of a declarationconst
modifies the previous token.There is a rationale behind this exception - for elementary declarations
const char c
looks for some people more natural thanchar const c
- and it is reported that a precursor form ofconst char c
predates the final const rule.getopt
or
Which means that
argv
is a pointer to const vector of pointers to non-const strings.But one would expect following declaration:
(pointer to const vector to const strings)
Because
getopt()
is not supposed to change the strings referenced via argv.At least
char **
(as used inmain()
) automatically converts tochar * const * argv
.Clang
Which means that
argv
is a pointer to a non-const array of pointers to const strings.Again one would expect
const char * const *argv
for the same reason as above.But this is more noticeable because
char **
does not convert toconst char **
, e.g.yields a compile error, where
and
do not.
const
修饰符很简单:它修改它前面的内容,除非在它之前没有任何东西。所以:
等。一般来说,最好避免前面没有任何内容的形式
const
,但在实践中,你会看到它们,所以你必须请记住,当
const
之前没有类型时,您必须在逻辑上将其移到第一种类型的后面。所以:
实际上是:
,即指向 const char 的指针。
最后,在函数声明中,后的
[]
读作前的*
。(再次强调,最好避免这种误导性的符号,但是
你将会看到它,所以你必须处理它。) 所以:
是:
指向 char 的 const 指针的指针。
The
const
modifier is trivial: it modifies what precedes it, unlessnothing precedes it. So:
, etc. Generally, It's best to avoid the forms where nothing precedes
the
const
, but in practice, you're going to see them, so you have toremember that when no type precedes the
const
, you have to logicallymove it behind the first type. So:
is in fact:
, i.e. pointer to pointer to const char.
Finally, in a function declaration, a
[]
after reads as a*
before.(Again, it's probably better to avoid this misleading notation, but
you're going to see it, so you have to deal with it.) So:
is:
a pointer to a const pointer to a char.