char * const和const char *有什么区别?


279

之间有什么区别:

char * const 

const char *


8
“ const”左侧的第一件事是常量。如果“ const”是最左边的东西,那么它右边的第一件事就是常量。
纸杯蛋糕

4
作为一个友好的提示,永远不要忘记cdecl是一回事。
Braden Best

还有另外一个字符常量*这是例外的返回类型::什么()

Answers:


363

不同的是,const char *是一个指针指向一个const char,而char * const是一个常量指针到char

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

还有一个

const char * const

这是指向常量char的常量指针(因此不能更改任何内容)。

注意:

以下两种形式是等效的:

const char *

char const *

确切的原因在C ++标准中进行了描述,但重要的是要注意并避免造成混淆。我知道一些喜欢的编码标准:

char const

过度

const char

(使用或不使用指针),以便const元素的位置与使用指针相同const


6
值得一提的是,如果在同一声明中指定多个变量会发生什么情况?我相信const int *foo,*bar;会声明foobar都为int const *,但int const *foo, *bar会声明fooint const *bar都为int *。我认为typedef int * intptr; const intptr foo,bar;将两个变量都声明为int * const;我不知道使用组合声明创建没有typedef的该类型的两个变量的任何方法。
supercat

1
@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 barbar?使其无论constvolatile?我想念Pascal对声明的变量名称及其类型的干净分隔(指向整数指针数组的指针将是var foo: ^Array[3..4] of ^Integer;`。我认为这是C中一些有趣的嵌套括号内的东西。)
supercat

3
@supercat(哦,仅C语言,对不起C ++代码链接,我从C ++问题中得到了答案)这全都与C声明语法有关,带有(“纯”)类型的部分,后跟一个声明符。在“ int const *foo, *volatile bar”中,类型部分是int const(在之前停止*),声明符是*foo(表达式*foo将表示int const)和*volatile bar从右到左读取(cv-qualifiers的好规则),foo是指向const int 的指针,并且bar是指向const int(指针本身是volatile,指向的int被[访问为] const)。
gx_

@supercat至于“一个指针,指针数组为整数”(我不知道帕斯卡,不知道的[3..4]语法,所以我们需要10个元素的数组)int *(*foo)[10];。它镜像了它(未来)用作表达式的用法:(*(*foo)[i]具有i整数,[0, 10)即ie [0, 9])将首先取消引用foo以获取数组,然后访问索引处的元素i(因为后缀[]绑定比prefix紧密*),然后取消引用该元素,最后产生一个int(请参阅ideone.com/jgjIjR)。但这typedef使它变得更容易(请参见ideone.com/O3wb7d)。
gx_

102

为避免混淆,请始终附加 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;

10
为什么?“避免混乱”并不能解释我的困惑。
Andrew Weir

14
@Andrew:我暗示的是一致性,因此可读性强。编写所有类型限定符以使它们始终修改左侧的内容,这是我使用的。
diapir 2013年

1
实际上,这是我在SO中找到的最佳答案
陷阱2014年

8
作为代码标准,我很少遇到这种样式,因此不太可能采用它。但是,作为一种学习工具,此答案非常有帮助!(所以我想太糟糕了,这不是更常见的样式。)
natevw 2014年

8
@Alla:p与类型无关:(const int *const)。无论是好是坏(如果您要我问更糟),C和C ++中的const限定词都应该是postfix:cf const member function void foo(int a) const;。声明的可能性const int是例外,而不是规则。
diapir 2015年

44

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

因此,这两个是相同的:

int const *i1;
const int *i2;

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

这个:

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

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



18

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


9

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


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指”。

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

8
  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 name,则指针将是恒定的,但是可以更改指向的位置,否则指针将指向恒定的位置,而指针可以指向另一个位置,但是指向的内容不能更改


1
“ char * const x是指常量的字符指针,但是它指向的位置可以更改。” 错误。不能更改位置本身的值。
2015年

3

第一个是语法错误。也许你的意思是

const char * mychar

char * const mychar

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


3

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

  1. * => 之前存储的常量
  2. * =>之后的指针本身是常量

3

许多答案提供了特定的技术,经验法则等,以了解此变量声明的特定实例。但是有一种通用的技术可以理解任何声明:

顺时针/螺旋法则

一个)

const char *a;

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

B)

char * const a;

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


1
也称为左右定律(至少这是我学到的):jdurrett.ba.ttu.edu/3345/handouts/RL-rule.html
Tomas Pruzina

(如果答案的实质不被隐藏在链接的后面,而这里的文字甚至没有引用或至少没有提及其任何具体细节,则超出了通用的“按规则”将是更好的选择。)
z

@Sz。在这里,您是否有任何具体的困惑可以清除?知道规则后,实际上并没有太多内容。
PnotNP '19

1

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

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

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

然后是const char * const,指针和字符无法更改。


您的前两个实际上是相同的,而第三个是编译器错误:)
workmad3,2009年

1

这是代码的详细说明

/*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;
}*/

@reese moore谢谢。
Megharaj

1
// 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’
}

1
  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 *var要么 datatype 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;
    }

1

char * const和const char *?

  1. 指向恒定值

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

  1. 指向值的常量指针

char * const p; //地址无法更改

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

const char * const p; //两者都无法更改。


1

const修改将立即应用于术语其左。唯一的例外是,当左边没有任何东西时,则适用于右边的东西。

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

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

是否依赖编译器?gcc为“ const char const *”,“ const const char *”和“ char const const *”产生相同的结果->指针可能指向其他位置。
cosinus0

1

两条规则

  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.

1

我想指出的是,int const *(或 const int *)与指向const int变量的指针无关,而是该变量const用于该特定指针。

例如:

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

上面的代码可以完美地编译。_p指向const变量,尽管var它本身不是常数。


1

我记得捷克书中有关C的文章:请阅读以变量开头并向左走的声明。因此对于

char * const a;

您可以将其理解为:“ a是类型为常量指针的变量,char”,

char const * a;

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

奖金:

const char * const a;

您将按原样阅读achar类型的常量变量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.