2012-04-10 144 views
125

以下声明有什么区别?常量指针vs常量值指针

char * const a; 
const char * a; 

为了理解上的差异,我写这个小程序:

#include <stdio.h> 
#include <stdlib.h> 


int main (int argc, char **argv) 
{ 
    char a = 'x'; 
    char b = 'y'; 

    char * const pc1 = &a; 
    const char * pc2 = &a; 

    printf ("Before\n"); 
    printf ("pc1=%p\n", pc1); 
    printf ("*pc1=%c\n", *pc1); 
    printf ("pc2=%p\n", pc2); 
    printf ("*pc2=%c\n", *pc2); 

    *pc1 = b; 
/*  pc1 = &b; */ 

/*  *pc2 = b; */ 
    pc2 = &b; 

    printf ("\n\n"); 

    printf ("After\n"); 
    printf ("pc1=%p\n", pc1); 
    printf ("*pc1=%c\n", *pc1); 
    printf ("pc2=%p\n", pc2); 
    printf ("*pc2=%c\n", *pc2); 

    return EXIT_SUCCESS; 
} 

我编译的程序(用gcc 3.4)并运行它。输出突出显示差异相当好:

Before 
pc1=ffbfd7e7 
*pc1=x 
pc2=ffbfd7e7 
*pc2=x 


After 
pc1=ffbfd7e7 
*pc1=y 
pc2=ffbfd7e6 
*pc2=x 

但是,我不得不编写小程序来获得答案。如果我远离机器(例如面试),我无法回答这个问题。

有人可以通过评论上面的例子解释const关键字的运作方式吗?

+6

更完整的答案如下,但我喜欢认为'const'绑定到下一个标记'。所以在'char * const a'中是'a',变量本身是不可修改的。在'const char * a'中,它是指向不可修改的字符。 – davmac 2014-05-20 10:05:48

+0

我认为标题应该像 - “常量指针vs指针”指向一个常量值“ – RBT 2016-09-21 00:23:58

回答

150
char * const a; 

意味着指针是恒定不变的,但指向的数据不是。
在这种情况下,您可以使用const_cast(使用C++)或c样式转换抛弃常量,因为数据本身不是常量。

const char * a; 

表示无法使用指针a写入指向的数据。 在这种情况下使用const_cast(C++)或C风格强制转换以抛出常量会导致未定义的行为

+43

const char * a' does ** not **表示”指向的数据是恒定且不可变的“。它只是'a'指针不能写入的指针。有针对性的数据可以由别人编写。例如:https://gist.github.com/andyli/b4107c8910208fe54764 – 2015-07-07 05:37:31

+3

@AndyLi有时候,*指向的数据可能会被其他人写入。或者,它可以是非常稳定的,例如一个字符串文字。 – EJP 2016-05-26 23:57:17

9

第一个是指向char的常量指针,第二个是指向常量char的指针。你没有触及所有的情况下,在你的代码:

char * const pc1 = &a; /* You can't make pc1 point to anything else */ 
const char * pc2 = &a; /* You can't dereference pc2 to write. */ 

*pc1 = 'c' /* Legal. */ 
*pc2 = 'c' /* Illegal. */ 

pc1 = &b; /* Illegal, pc1 is a constant pointer. */ 
pc2 = &b; /* Legal, pc2 itself is not constant. */ 
+0

谢谢你的解释,但我已经达到了这些结果(如我在我的问题中粘贴的代码所示)。我正在寻找某人来解释const操作符是如何工作的以及如何解释哪些实体是合格的,而无需在机器上运行代码来测试它。 – rahmu 2012-04-10 16:08:23

59
char * const a; 

*a是可写的,但a不大;换句话说,您可以通过a修改指向的值,但不能修改a本身。 a指向char的常数指针。

const char * a; 

a是可写的,但*a不大;换句话说,您可以修改a(将其指向新的位置),但不能修改指向的值,作者为a

注意,这是相同的

char const * a; 

在这种情况下,a指针const char

63

要解析复杂的类型,您需要从变量开始,向左并向外旋转。如果没有任何数组或函数需要担心(因为它们位于变量名称的右侧),这会成为从右向左读取的情况。

因此,与char *const a;你有a,这是一个const指针(*)到char。换句话说,您可以更改a指向的字符,但不能使a指向任何不同的字符。

相反与const char* b;你有b,这是一个指针(*)到char这是const。您可以使用b指向任何您喜欢的字符,但不能使用*b = ...;更改该字符的值。

您当然也可以同时具有两种风格的风格:const char *const c;

+8

一流的回应。不仅提供了答案,还教育读者如何解析这些类型的声明。我还推荐http://cdecl.org/作为将声明转换为有意义的英文文本(例如int(*(* foo)(void))[3]的网站(“将foo声明为函数指针(void)返回指向int的数组3的指针“)。 – jarmod 2015-07-05 15:42:51

17

现在您知道char * const aconst char * a之间的区别。很多时候,如果它的常量指针或指针指向一个常量变量,我们会感到困惑。

如何阅读?按照下面的简单步骤来确定上面两个。

让我们来看看如何从右至左

阅读以下声明

char * const a; 

读现在开始a

1。相邻aconst

char * (const a);

--->所以aconstant(????)

2。现在一起去吧*

char (* (const a));

--->所以aconstantpointer(????)

3。沿着,有char

(char (* (const a)));

--->aconstantpointercharacter可变

a is constant pointer to character variable. 

是不是很容易读?

对于相若方式第二个声明

const char * a; 

现在再次a开始,

1。相邻a*

--->因此apointer至(????)

2。现在有char

--->所以apointercharacter

嗯,这没有任何意义!所以洗牌pointercharacter

--->所以acharacterpointer(?????)

3。现在你有constant

--->所以acharacterpointerconstant可变

但是,尽管你可以出什么声明意味着,让我们使声音更明智。

a is pointer to constant character variable 
+0

清除东西的好方法! :) – LordTitiKaka 2014-10-18 11:40:16

+0

这不是AAT答案的更详细版本吗? – MestreLion 2015-02-20 05:19:34

+1

哦,我没有看到。我的教授在我的工程中教给我这种方法。希望它对初学者有所帮助。 – 2015-02-20 08:19:14

13

理解差异的最简单方法是考虑不同的可能性。有两个对象需要考虑,指针和指向的对象(在这种情况下,“a”是指针的名称,指向的对象是未命名的,类型为char)。这种可能性是:

  1. 没有什么是常量
  2. 指针是常量
  3. 指向的对象是常量
  4. 两个指针和指向的对象是常量。

这些不同的可能性可以在C如下表示:

  1. 字符*一个;
  2. char * const a;
  3. const char * a;
  4. const char * const a;

我希望这说明可能存在差异

5

以上是伟大的答案。下面是一个简单的方法来记住这一点:

一个是一个指针

*一个是价值

现在如果你说“常量一”,那么指针是常量。 (即char * const a;)

如果你说“const * a”,那么值是const。 (即为const char *一)

2

您可以使用CDECL实用程序或它的在线版本,像http://www.lemoda.net/c/cdecl/

例如:

void (* x)(int (*[])());declare x as pointer to function (array of pointer to function returning int) returning void

1

试图用简单的方式来回答:

char * const a; => a is (const) constant (*) pointer of type char {L <- R}. =>(Constant Pointer) 
const char * a; => a is (*) pointer to char constant    {L <- R}. =>(Pointer to Constant) 

常指针:

指针是恒定的!即它所持有的地址不能改变。它将被存储在只读存储器中。

让我们尝试改变指针的地址,了解更多:

char * const a = &b; 
char c; 
a = &c; // illegal , you can't change the address. `a` is const at L-value, so can't change. `a` is read-only variable. 

这意味着一旦固定指针指向一些东西它是永恒的。

指针a只有分数b

但是你可以改变的b例如值:

char b='a'; 
char * const a =&b; 

printf("\n print a : [%c]\n",*a); 
*a = 'c'; 
printf("\n now print a : [%c]\n",*a); 

指针常数:

值由指针指向不能改变。

const char *a; 
char b = 'b'; 
const char * a =&b; 
char c; 
a=&c; //legal 

*a = 'c'; // illegal , *a is pointer to constant can't change!. 
0
const char * a; 

此状态指针恒定字符。 例如。

char b='s'; 
const char *a = &b; 

这里a指向一个恒定的字符(“S”,在这种情况下)。你不能使用a更改value.But这一声明并不意味着它指向的是真的值一个常数,它只是意味着该值是一个常数,就a而言。 您可以通过更改b的值直接更改b的值,但不能通过a指针间接更改值。

*a='t'; //INVALID b='t' ; //VALID

char * const a=&b 

这指出一个恒定字符指针。 它约束a仅指向b,但它允许您更改b的值。

希望它有帮助!:)

6

我会口头先解释一个例子:

指针对象可以被声明为常量指针或指向const对象(或两者):

const指针不能被重新分配以指向与最初分配的对象不同的对象,但它可以用于修改它指向的对象(称为“指针”)。
引用变量因此是常量指针的替代语法。

指针const对象,在另一方面,可以被重新分配给指向同一类型或可转换类型的另一个目的,但它不能被用来修改任何对象。

A const指针常量对象也可以声明,既不能用于修改指针,也不能被重新分配指向另一个对象。

例子:

void Foo(int * ptr, 
     int const * ptrToConst, 
     int * const constPtr, 
     int const * const constPtrToConst) 
{ 
    *ptr = 0; // OK: modifies the "pointee" data 
    ptr = 0; // OK: modifies the pointer 

    *ptrToConst = 0; // Error! Cannot modify the "pointee" data 
    ptrToConst = 0; // OK: modifies the pointer 

    *constPtr = 0; // OK: modifies the "pointee" data 
    constPtr = 0; // Error! Cannot modify the pointer 

    *constPtrToConst = 0; // Error! Cannot modify the "pointee" data 
    constPtrToConst = 0; // Error! Cannot modify the pointer 
} 

乐意提供帮助!祝你好运!