【问题标题】:What is the difference between char * const and const char *?char * const 和 const char * 有什么区别?
【发布时间】:2010-10-27 19:02:16
【问题描述】:

两者有什么区别:

char * const 

const char *

【问题讨论】:

标签: c pointers constants


【解决方案1】:

区别在于const char * 是指向const char 的指针,而char * const 是指向char 的常量指针。

首先,被指向的值不能改变,但指针可以。第二,被指向的值可以改变,但指针不能改变(类似于引用)。

还有一个

const char * const

它是一个指向常量 char 的常量指针(所以不能改变它)。

注意:

以下两种形式是等价的:

const char *

char const *

确切的原因在 C++ 标准中有所描述,但重要的是要注意并避免混淆。我知道几种更喜欢的编码标准:

char const

结束

const char

(带或不带指针)以便const 元素的位置与带指针const 的位置相同。

【讨论】:

  • 如果在同一个声明中指定多个变量会发生什么值得注意吗?我相信const int *foo,*bar; 会声明foobarint const *,但int const *foo, *bar 将声明fooint const *barint *。我认为typedef int * intptr; const intptr foo,bar; 会将两个变量都声明为int * const;我不知道有什么方法可以使用组合声明来创建没有 typedef 的该类型的两个变量。
  • @supercat I believe const int *foo,*bar; would declare both foo and bar to be int const *:是的。 but int const *foo, *bar would declare foo to be a int const * and bar to be int *不!这将与之前的情况完全相同。 (请参阅ideone.com/RsaB7n,您会在 foo 和 bar 中得到相同的错误)。 I think typedef int * intptr; const intptr foo,bar; would declare both variables to be int * const:是的。 I don't know any way to use a combined declaration to create two variables of that type without a typedef:嗯,int *const foo, *const bar;。 C 声明符语法...
  • @gx_:所以我错了——我的不确定性是为什么我建议说出规则是什么可能会有所帮助。 int const *foo, *volatile bar 会对 bar 做什么?将其设为constvolatile?我想念 Pascal 对声明变量名称及其类型的清晰分离(指向整数指针数组的指针将是 var foo: ^Array[3..4] of ^Integer;`。我认为那将是 C 中一些有趣的嵌套括号内容。
  • @supercat(哦,仅限 C,对不起 C++ 代码链接,我是从 C++ 问题中得到的)这完全是关于 C 声明语法,带有 ( "pure") type 部分后跟 declarator。在“int const *foo, *volatile bar”中,类型部分是int const(在* 之前停止),声明符是*foo(表达式*foo 将表示int const)和*volatile bar;阅读 从右到左cv-qualifiers 的好规则),foo 是指向 const int 的指针,@987654364 @ 是一个指向 const int 的 volatile 指针(指针本身是 volatile,指向的 int [访问为] const)。
  • @supercat 至于“指向整数指针数组的指针”(我不知道 Pascal,不确定 [3..4] 语法,所以我们取一个包含 10 个元素的数组) :int *(*foo)[10];。它反映了它(未来)作为表达式的用途:*(*foo)[i]i[0, 10) 范围内的整数,即[0, 9])将首先取消引用foo 以获取数组,然后访问索引处的元素i(因为后缀 [] 比前缀 * 绑定得更紧密),然后取消引用此元素,最终生成 int(参见 ideone.com/jgjIjR)。但是typedef 让它更容易(参见ideone.com/O3wb7d)。
【解决方案2】:

为避免混淆,请始终附加 const 限定符。

int       *      mutable_pointer_to_mutable_int;
int const *      mutable_pointer_to_constant_int;
int       *const constant_pointer_to_mutable_int;
int const *const constant_pointer_to_constant_int;

【讨论】:

  • 为什么? “为了避免混淆”并没有解释我的困惑是什么。
  • @Andrew:我在暗示一致性和可读性。编写所有类型限定符,以便它们修改左侧的内容,总是,这是我使用的。
  • 实际上这是我在 SO 中找到的主题的最佳答案
  • 作为代码标准,我很少遇到这种风格,所以不太可能采用。然而,作为一个学习工具,这个答案非常有帮助! (所以我想这不是更常见的风格太糟糕了。)
  • @Alla: p 与类型无关:(const int *const)。无论好坏(如果你问我,更糟)C 和 C++ 中的 const 限定符都是后缀:cf const member function void foo(int a) const;。声明const int 的可能性是例外而不是规则。
【解决方案3】:

const 总是修改它之前的东西(在它的左边),除非它是类型声明中的第一个东西,它会修改它之后的东西(在它的右边)。

所以这两个是一样的:

int const *i1;
const int *i2;

它们定义了指向const int 的指针。您可以更改i1i2 指向的位置,但不能更改它们指向的值。

这个:

int *const i3 = (int*) 0x12345678;

定义一个指向整数的const指针,并将其初始化为指向内存位置12345678。您可以更改地址12345678处的int值,但不能更改i3指向的地址。

【讨论】:

    【解决方案4】:

    const char* 是指向常量字符的指针
    char* const 是指向字符的常量指针
    const char* const 是指向常量字符的常量指针

    【讨论】:

      【解决方案5】:

      const * char 是无效的 C 代码,没有意义。也许您想问const char *char const * 之间的区别,或者const char *char * const 之间的区别?

      另见:

      【讨论】:

        【解决方案6】:

        经验法则:从右到左阅读定义!


        const int *foo;

        表示“foo 指向 (*) 到无法更改的 int (const)”。
        对于程序员来说,这意味着“我不会改变foo 所指向的”。

        • *foo = 123;foo[0] = 123; 将无效。
        • foo = &bar; 是允许的。

        int *const foo;

        表示“foo 不能更改 (const) 并将 (*) 指向 int”。
        对于程序员来说,这意味着“我不会更改foo 所指的内存地址”。

        • 允许使用 *foo = 123;foo[0] = 123;
        • foo = &bar; 无效。

        const int *const foo;

        表示“foo 无法更改 (const) 并指向 (*) 无法更改的 int (const)”。
        对于程序员来说,这意味着“我不会改变foo 所指的,也不会改变foo 所指的地址”。 p>

        • *foo = 123;foo[0] = 123; 将无效。
        • foo = &bar; 将无效。

        【讨论】:

          【解决方案7】:
          1. const char* x这里的X基本上是一个字符指针,它指向一个常数值

          2. char* const x是指字符指针,它是常量,但它指向的位置可以改变。

          3. const char* const x是1和2的组合,表示它是一个指向常量值的常量字符指针。

          4. const *char x 将导致编译器错误。不能声明。

          5. char const * x 等于点 1。

          经验法则是,如果 const 带有 var 名称,则 指针将保持不变,但指向的位置可以更改,否则 指针将指向一个恒定的位置和指针可以指向另一个位置,但指向的位置内容不能改变

          【讨论】:

          • "char* const x 是指字符指针,它是常量,但它指向的位置可以改变。"错误的。位置的值可以更改,而不是位置本身。
          【解决方案8】:

          第一个是语法错误。也许你的意思是之间的区别

          const char * mychar
          

          char * const mychar
          

          在这种情况下,第一个是指向无法更改的数据的指针,第二个是始终指向相同地址的指针。

          【讨论】:

            【解决方案9】:

            另一个经验法则是检查 const 在哪里

            1. before * => 存储为常量
            2. after * => pointer 本身是常量

            【讨论】:

              【解决方案10】:

              很多答案都提供了具体的技术、经验法则等来理解这个特定的变量声明实例。但是有一种通用的技术可以理解任何声明:

              Clockwise/Spiral Rule

              一)

              const char *a;
              

              根据顺时针/螺旋规则a 是指向常量字符的指针。这意味着字符是恒定的,但指针可以改变。即a = "other string"; 很好,但a[2] = 'c'; 将无法编译

              B)

              char * const a;
              

              根据规则,a 是指向字符的 const 指针。即你可以做a[2] = 'c';,但你不能做a = "other string";

              【讨论】:

              • 也称为左右规则(至少我是这么学的):jdurrett.ba.ttu.edu/3345/handouts/RL-rule.html
              • (如果答案的本质不会隐藏在链接后面会更好,这里的文字甚至没有引用或至少提到其任何细节,超出了通用“按照规则”。)
              • @Sz。你有什么具体的困惑我可以澄清吗?知道了规矩之后真的没什么大不了的。
              【解决方案11】:

              char * const 和 const char *?

              1. 指向一个常数值

              const char * p; // 值不能改变

              1. 指向值的常量指针

              char * const p; //地址不能更改

              1. 指向常量值的常量指针

              const char * const p; // 两者都不能更改。

              【讨论】:

                【解决方案12】:

                我想你的意思是 const char * 和 char * const 。

                第一个,const char *,是一个指向常量字符的指针。指针本身是可变的。

                第二个,char * const 是一个指向字符的常量指针。指针不能改变,它指向的字符可以。

                然后就是指针和字符不能改变的const char * const。

                【讨论】:

                • 你的前两个实际上是一样的,你的第三个是编译器错误:)
                【解决方案13】:

                这里有详细的代码说明

                /*const char * p;
                char * const p; 
                const char * const p;*/ // these are the three conditions,
                
                // const char *p;const char * const p; pointer value cannot be changed
                
                // char * const p; pointer address cannot be changed
                
                // const char * const p; both cannot be changed.
                
                #include<stdio.h>
                
                /*int main()
                {
                    const char * p; // value cannot be changed
                    char z;
                    //*p = 'c'; // this will not work
                    p = &z;
                    printf(" %c\n",*p);
                    return 0;
                }*/
                
                /*int main()
                {
                    char * const p; // address cannot be changed
                    char z;
                    *p = 'c'; 
                    //p = &z;   // this will not work
                    printf(" %c\n",*p);
                    return 0;
                }*/
                
                
                
                /*int main()
                {
                    const char * const p; // both address and value cannot be changed
                    char z;
                    *p = 'c'; // this will not work
                    p = &z; // this will not work
                    printf(" %c\n",*p);
                    return 0;
                }*/
                

                【讨论】:

                  【解决方案14】:
                  // Some more complex constant variable/pointer declaration.
                  // Observing cases when we get error and warning would help
                  // understanding it better.
                  
                  int main(void)
                  {
                    char ca1[10]= "aaaa"; // char array 1
                    char ca2[10]= "bbbb"; // char array 2
                  
                    char *pca1= ca1;
                    char *pca2= ca2;
                  
                    char const *ccs= pca1;
                    char * const csc= pca2;
                    ccs[1]='m';  // Bad - error: assignment of read-only location ‘*(ccs + 1u)’
                    ccs= csc;    // Good
                  
                    csc[1]='n';  // Good
                    csc= ccs;    // Bad - error: assignment of read-only variable ‘csc’
                  
                    char const **ccss= &ccs;     // Good
                    char const **ccss1= &csc;    // Bad - warning: initialization from incompatible pointer type
                  
                    char * const *cscs= &csc;    // Good
                    char * const *cscs1= &ccs;   // Bad - warning: initialization from incompatible pointer type
                  
                    char ** const cssc=   &pca1; // Good
                    char ** const cssc1=  &ccs;  // Bad - warning: initialization from incompatible pointer type
                    char ** const cssc2=  &csc;  // Bad - warning: initialization discards ‘const’
                                                 //                qualifier from pointer target type
                  
                    *ccss[1]= 'x'; // Bad - error: assignment of read-only location ‘**(ccss + 8u)’
                    *ccss= ccs;    // Good
                    *ccss= csc;    // Good
                    ccss= ccss1;   // Good
                    ccss= cscs;    // Bad - warning: assignment from incompatible pointer type
                  
                    *cscs[1]= 'y'; // Good
                    *cscs= ccs;    // Bad - error: assignment of read-only location ‘*cscs’
                    *cscs= csc;    // Bad - error: assignment of read-only location ‘*cscs’
                    cscs= cscs1;   // Good
                    cscs= cssc;    // Good
                  
                    *cssc[1]= 'z'; // Good
                    *cssc= ccs;    // Bad - warning: assignment discards ‘const’
                                   //                qualifier from pointer target type
                    *cssc= csc;    // Good
                    *cssc= pca2;   // Good
                    cssc= ccss;    // Bad - error: assignment of read-only variable ‘cssc’
                    cssc= cscs;    // Bad - error: assignment of read-only variable ‘cssc’
                    cssc= cssc1;   // Bad - error: assignment of read-only variable ‘cssc’
                  }
                  

                  【讨论】:

                    【解决方案15】:
                    1. 常量指针:常量指针在整个程序过程中只能指向相应数据类型的单个变量。我们可以改变指针所指向的变量的值。初始化应在声明期间完成。

                    语法:

                    datatype *const var;
                    

                    char *const属于这种情况。

                    /*program to illustrate the behaviour of constant pointer */
                    
                    #include<stdio.h>
                    int main(){
                      int a=10;
                      int *const ptr=&a;
                      *ptr=100;/* we can change the value of object but we cannot point it to another variable.suppose another variable int b=20; and ptr=&b; gives you error*/
                      printf("%d",*ptr);
                      return 0;
                    }
                    
                    1. 指向 const 值的指针:在这种情况下,指针可以指向相应类型的任意数量的变量,但我们无法在特定时间更改指针所指向的对象的值。

                    语法:

                    const datatype *vardatatype const *var

                    const char*属于这种情况。

                    /* program to illustrate the behavior of pointer to a constant*/
                    
                       #include<stdio.h>
                       int main(){
                           int a=10,b=20;
                           int const *ptr=&a;
                           printf("%d\n",*ptr);
                           /*  *ptr=100 is not possible i.e we cannot change the value of the object pointed by the pointer*/
                           ptr=&b;
                           printf("%d",*ptr);
                           /*we can point it to another object*/
                           return 0;
                        }
                    

                    【讨论】:

                      【解决方案16】:

                      const 修饰符应用于紧靠其左侧的术语。唯一的例外是当它的左边没有任何东西时,它适用于它右边的东西。

                      这些都是说“指向常量char的常量指针”的等效方式:

                      • const char * const
                      • const char const *
                      • char const * const
                      • char const const *

                      【讨论】:

                      • 是否依赖于编译器? gcc 为 "const char const *" 和 "const const char *" 和 "char const const *" 产生相同的结果 -> 指针可以指向其他位置。
                      【解决方案17】:

                      两条规则

                      1. If const is between char and *, it will affect the left one.
                      2. If const is not between char and *, it will affect the nearest one.

                      例如

                      1. char const *. This is a pointer points to a constant char.
                      2. char * const. This is a constant pointer points to a char.

                      【讨论】:

                        【解决方案18】:

                        我想指出的是,使用int const *(或const int *)并不是指向一个const int变量的指针,而是这个变量是const这个特定的指针。

                        例如:

                        int var = 10;
                        int const * _p = &var;
                        

                        上面的代码编译得很好。 _p 指向一个 const 变量,虽然 var 本身不是常量。

                        【讨论】:

                          【解决方案19】:

                          我记得捷克关于 C 的书:阅读声明,你从变量开始,然后向左走。 所以对于

                          char * const a;
                          

                          您可以读作:“a 是指向char 的常量指针类型的变量”,

                          char const * a;
                          

                          您可以读作:“a 是指向 char 类型的常量变量的指针。我希望这会有所帮助。

                          奖金:

                          const char * const a;
                          

                          您将读作a 是指向 char 类型常量变量的常量指针。

                          【讨论】:

                            猜你喜欢
                            • 2014-02-15
                            • 2012-12-26
                            • 2013-04-23
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2018-11-05
                            • 2012-04-07
                            相关资源
                            最近更新 更多