常量字符*常量与常量字符*? 我正在通过一些示例程序来重新熟悉C++,我已经遇到了下面的问题。首先,下面是示例代码: void print_string(const char * the_string) { cout << the_string << endl; } int main () { print_string("What's up?"); } void打印字符串(常量字符*字符串) { 两者之间的区别在于char*可以指向任意指针。相反,Const char*指向可执行文件数据部分中定义的常量。因此,您不能修改Const char*字符串的字符值。

常量字符*常量与常量字符*? 我正在通过一些示例程序来重新熟悉C++,我已经遇到了下面的问题。首先,下面是示例代码: void print_string(const char * the_string) { cout << the_string << endl; } int main () { print_string("What's up?"); } void打印字符串(常量字符*字符串) { 两者之间的区别在于char*可以指向任意指针。相反,Const char*指向可执行文件数据部分中定义的常量。因此,您不能修改Const char*字符串的字符值。,c++,c,C++,C,在后者中,您保证不会同时修改f中的指针和字符首先,你只能保证内容不会改变,但你可以移动指针,后者可以防止你修改打印字符串中的字符串。这实际上是合适的,但可能会让开发人员感到厌烦 char*字符:我可以更改字符指向的char,也可以修改它指向的char const char*字符串:我可以更改字符串指向的字符,但我不能修改它指向的字符 char*const the_string:我无法更改该_string指向的char,但我可以修改它指向的char const char*const the_str

在后者中,您保证不会同时修改f中的指针和字符首先,你只能保证内容不会改变,但你可以移动指针,后者可以防止你修改
打印字符串中的
字符串。这实际上是合适的,但可能会让开发人员感到厌烦

char*字符
:我可以更改字符
指向的
char
,也可以修改它指向的
char

const char*字符串
:我可以更改字符串
指向的字符,但我不能修改它指向的字符

char*const the_string
:我无法更改该_string
指向的
char
,但我可以修改它指向的
char

const char*const the_string
:我无法更改该_string
指向的
char
,也无法修改它指向的
char

  • 指向可变字符的可变指针

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

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

    char *p;
    
    const char *p;
    
    char * const p; 
    
    const char * const p;
    
  • 指向常量字符的常量指针

    char *p;
    
    const char *p;
    
    char * const p; 
    
    const char * const p;
    

  • 任何一个都不起作用是没有理由的。所有的
    print\u string()
    都是打印值。它不会试图修改它

    让不修改的函数将参数标记为常量是一个好主意。优点是不能更改(或您不想更改)的变量可以毫无错误地传递给这些函数


    至于确切的语法,您需要指出哪种类型的参数可以“安全”地传递给函数。

    const char*const
    表示指针以及指针指向的数据都是常量


    const char*
    仅表示指针指向的数据是常量。但指针本身不是常量

    例如

    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. 
    

    许多人建议从右到左阅读类型说明符

    const char * // Pointer to a `char` that is constant, it can't be changed.
    const char * const // A const pointer to const data.
    
    在这两种形式中,指针都指向常量或只读数据


    在第二种形式中,指针不能更改;指针将始终指向相同的位置。

    不同之处在于,如果没有额外的
    常量,程序员可以在方法内部更改指针指向的位置;例如:

     void print_string(const char * the_string)
     {
        cout << the_string << endl;
        //....
        the_string = another_string();
        //....
    
     }
    
    void打印字符串(常量字符*字符串)
    {
    
    cout我认为它很少相关,因为您的函数不会使用诸如&*the_字符串或**the_字符串之类的参数调用。指针本身是一个值类型参数,因此即使您修改它,也不会更改用于调用函数的副本。您显示的版本确保字符串不会更改,我认为在这种情况下这就足够了。

    const char*
    意味着您不能使用指针来更改指向的内容。不过,您可以将指针更改为指向其他内容

    考虑:

    const char * promptTextWithDefault(const char * text)
    {
        if ((text == NULL) || (*text == '\0'))
            text = "C>";
        return text;
    }
    
    该参数是指向常量字符的非常量指针,因此可以将其更改为另一个
    const char*
    值(如常量字符串)。但是,如果我们错误地编写了
    *text='\0'
    ,则会出现编译错误

    可以说,如果您不想更改参数所指向的内容,您可以将参数
    const char*const text
    ,但这样做并不常见。我们通常允许函数更改传递给参数的值(因为我们按值传递参数,任何更改都不会影响调用者)


    顺便说一句:避免
    char*const*
    是一种很好的做法,因为它经常被误读-它的意思与
    const*char*
    相同,但太多人将其理解为
    char*const

    几乎所有其他答案都是正确的,但他们忽略了一个方面:在参数上使用额外的
    const
    在函数声明中,编译器基本上会忽略它。现在,让我们忽略示例作为指针的复杂性,只使用
    int

    void foo(const int x);
    
    声明与相同的函数

    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
    }
    
    //这些声明是等效的
    无效打印字符串(常量字符*常量字符串);
    无效打印字符串(常量字符*字符串);
    //在此定义中,您不能更改
    //函数体。它本质上是一个常量局部变量。
    无效打印字符串(常量字符*常量字符串){
    cout(我知道这很旧,但我还是想和大家分享。)

    我只是想详细说明一下Thomas Matthews的答案。C类型声明的左右规则基本上是这样的:当阅读C类型声明时,从标识符开始,可以时向右,不能时向左

    最好用几个例子来解释这一点:

    例1
    • 从标识符开始,我们不能向右走
      const char* const* (*foo[8])()
                ^
      
      const char* const* (*foo[8])()
            ^^^^
      
      const char* const* (*foo[8])()
      ^^^^^