const char * const与const char *?
我正在运行一些示例程序来熟悉C ++,我遇到了以下问题。 首先,这里是示例代码:
void print_string(const char * the_string) { cout << the_string << endl; } int main () { print_string("What's up?"); }
在上面的代码中,print_string的参数可以是const char * const the_string
。 哪一个更准确呢?
我明白不同的是,一个是指向一个常量字符的指针,而另一个是指向一个常量字符的常量指针。 但为什么这两个工作呢? 什么时候它是相关的?
后者阻止你修改print_string
the_string
。 在这里实际上是适当的,但是也许冗长会让开发人员感到厌烦。
char* the_string
:我可以改变char
指向的char
,我可以修改它指向的char
。
const char* the_string
:我可以改变指向哪个the_string
,但是我不能修改它指向的char
。
char* const the_string
:我无法更改the_string
指向的char
,但我可以修改它指向的char
。
const char* const the_string
:我不能改变指向的the_string
,也不能修改它指向的char
。
-
指向可变字符的可变指针
char *p;
-
指向一个常量字符的可变指针
const char *p;
-
常量指向可变字符的指针
char * const p;
-
常量指针指向一个常量字符
const char * const p;
const char * const
表示指针以及指针指向的数据,都是const!
const char *
意味着只有指针指向的数据是const。 但是指针本身并不是const的。
例。
const char *p = "Nawaz"; p[2] = 'S'; //error, changing the const data! p="Sarfaraz"; //okay, changing the non-const pointer. const char * const p = "Nawaz"; p[2] = 'S'; //error, changing the const data! p="Sarfaraz"; //error, changing the const pointer.
许多人build议从右到左阅读types说明符。
const char * // Pointer to a `char` that is constant, it can't be changed. const char * const // A const pointer to const data.
在这两种forms中,指针指向常量或只读数据。
在第二种forms中,指针不能被改变; 指针总是指向相同的地方。
(我知道这是旧的,但我仍想分享。)
只是想详细说明托马斯马修斯的答案。 C型声明的左右规则几乎说:当读取一个C型声明开始在标识符上,当你可以时去,而当你不能时,离开。
这个最好用几个例子来解释:
例1
-
从标识符开始,我们不能向右走,所以我们走了
const char* const foo ^^^^^
foo是一个常量 …
-
继续向左
const char* const foo ^
foo是一个常量指针 …
-
继续向左
const char* const foo ^^^^
foo是一个常量指针char …
-
继续向左
const char* const foo ^^^^^
foo是一个常量指针,指向char 常量 (完成!)
例2
-
从标识符开始,我们不能向右走,所以我们走了
char* const foo ^^^^^
foo是一个常量 …
-
继续向左
char* const foo ^
foo是一个常量指针 …
-
继续向左
char* const foo ^^^^
foo是一个指向char的常量指针(Complete!)
例1337
-
从标识符开始,现在我们可以走了!
const char* const* (*foo[8])() ^^^
foo是一个8的数组 …
-
左括号,所以不能再去正确的,左转
const char* const* (*foo[8])() ^
foo是一个8 指针数组…
-
在括号内完成,现在可以去正确的
const char* const* (*foo[8])() ^^
foo是一个指向函数返回的8个指针的数组…
-
没有更多的权利,向左走
const char* const* (*foo[8])() ^
foo是指向函数的8个指针的数组,返回一个指向 …
-
继续向左
const char* const* (*foo[8])() ^^^^^
foo是一个8位指针的数组,该函数返回一个指向常量的指针。
-
继续向左
const char* const* (*foo[8])() ^
foo是一个指向函数的8个指针的数组,返回指向常量指针的指针 …
-
继续向左
const char* const* (*foo[8])() ^^^^
foo是一个8位指针数组的指针,它返回一个指向char的常量指针的指针…
-
继续向左
const char* const* (*foo[8])() ^^^^^
foo是8个指向函数的指针的数组,返回一个指向char 常量的常量指针的指针(Complete!)
进一步的解释: http : //www.unixwiz.net/techtips/reading-cdecl.html
不同的是,没有额外的const
,程序员可以在指针所指向的方法内改变; 例如:
void print_string(const char * the_string) { cout << the_string << endl; //.... the_string = another_string(); //.... }
这将是非法的,如果签名是void print_string(const char * const the_string)
许多程序员感觉过于冗长(在大多数情况下)额外的const
关键字,并忽略它,即使它在语义上是正确的。
在后者,你是保证不修改指针和字符在第一你只能保证内容不会改变,但你可以移动指针
没有任何一个人不能工作的原因。 所有的print_string()
都是打印这个值。 它不会尝试修改它。
使函数不会修改标记参数为const是一个好主意。 好处是不能改变的variables(或者你不想改变)可以传递给这些函数而不会出错。
至于确切的语法,你想要指出哪些types的参数是“安全”传递给函数。
我认为它很less有相关性,因为你的函数没有被调用像&* the_string或** the_string这样的参数。 指针本身是一个值types的参数,所以即使你修改它,你也不会改变用来调用函数的副本。 你显示的版本确保string不会改变,我认为在这种情况下就足够了。
const char *
意味着你不能使用指针来改变指向的内容。 不过,你可以改变指针指向别的东西。
考虑:
const char * promptTextWithDefault(const char * text) { if ((text == NULL) || (*text == '\0')) text = "C>"; return text; }
该参数是一个非常量指针的const char,所以它可以改变为另一个const char *
值(像一个常量string)。 但是,如果我们错误地写了*text = '\0'
那么我们会得到一个编译错误。
可以说,如果你不打算改变参数指向什么,你可以使参数为const char * const text
,但这样做并不常见。 我们通常允许函数更改传递给参数的值(因为我们通过值传递参数,任何更改都不会影响调用者)。
顺便说一句:避免char const *
是一个很好的习惯,因为它经常被误读 – 它和const char *
是一样的,但是太多人把它看作是char * const
。
几乎所有其他的答案都是正确的,但是却错过了一个方面:当你在一个函数声明的参数中使用额外的const
时,编译器会基本上忽略它。 有一段时间,让我们忽略你的例子作为一个指针的复杂性,只是使用一个int
。
void foo(const int x);
声明与。相同的function
void foo(int x);
只有在函数的定义中,额外的const
才有意义:
void foo(const int x) { // do something with x here, but you cannot change it }
这个定义与上面的任何一个声明兼容。 调用者不关心x
是否为const
– 这是与调用站点无关的实现细节。
如果你有一个const
指针指向const
数据,那么相同的规则适用:
// these declarations are equivalent void print_string(const char * const the_string); void print_string(const char * the_string); // In this definition, you cannot change the value of the pointer within the // body of the function. It's essentially a const local variable. void print_string(const char * const the_string) { cout << the_string << endl; the_string = nullptr; // COMPILER ERROR HERE } // In this definition, you can change the value of the pointer (but you // still can't change the data it's pointed to). And even if you change // the_string, that has no effect outside this function. void print_string(const char * the_string) { cout << the_string << endl; the_string = nullptr; // OK, but not observable outside this func }
很less有C ++程序员不愿意将参数设为const
,即使它们可能是const
,而不pipe这些参数是否是指针。
两者的区别在于char *可以指向任意的指针。 const char *相反,指向在可执行文件的DATA部分中定义的常量。 而且,因此,您不能修改const char *string的字符值。