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

  1. 指向可变字符的可变指针

     char *p; 
  2. 指向一个常量字符的可变指针

     const char *p; 
  3. 常量指向可变字符的指针

     char * const p; 
  4. 常量指针指向一个常量字符

     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的字符值。