常量指针 vs 指向常量的指针

268

我想知道两者之间的差异

const int* ptr;

以及

int * const ptr; 

它是如何工作的。

对我而言,理解和记住这个还是比较困难的。 请帮忙。


5
阅读Peter Linden所著《Deep C Secrets》书中的第三章“Unscrambling Declarations in C”,您将学习如何解密任何具有指针、常量等组合的复杂声明。 - Deepthought
1
重复问题在这里:https://dev59.com/LnNA5IYBdhLWcg3wn_U1,而不是之前关闭的那个问题,因为后者是关于C++的。 - alk
@user694733 在另一方面,它让我感受到开发者们有多么想为社区做出贡献,问题的状态对他们来说并不重要......有时候 :) - RBT
8个回答

457
const int* ptr; 

声明ptr是一个指向const int类型的指针。你可以修改ptr本身,但是不能修改ptr所指向的对象。

const int a = 10;
const int* ptr = &a;  
*ptr = 5; // wrong
ptr++;    // right  

虽然

int * const ptr;  

声明ptr为指向int类型的const指针。你不被允许修改ptr本身,但是可以修改ptr所指向的对象。

int a = 10;
int *const ptr = &a;  
*ptr = 5; // right
ptr++;    // wrong

通常我更喜欢这种声明方式,它使阅读和理解变得容易(从右到左阅读):

int const  *ptr; // ptr is a pointer to constant int 
int *const ptr;  // ptr is a constant pointer to int

13
我刚意识到,即使是这段代码int i = 10; const int* ptr = &i;也可以使用。这意味着ptr并不总是指向一个常量值。你也可以通过它指向一个变量值。只是你永远无法修改ptr所指向的值。 - RBT
7
即使这是一个重复的答案,它仍然是最好的...... - GeertVc
1
关于我经常访问这个页面的事实,您有没有在脑海中进行类比以更好地记住区别?如果您能告诉我们,那将非常棒! - Cătălina Sîrbu
1
@JinKwon 当然你可以这样做,但它会有完全不同的含义。 - haccks
3
@JinKwon const int * const a 声明 a 为指向 const intconst 指针。在这种情况下,既不能修改 a,也不能通过 *a 修改 a 所指向的对象。 - haccks
显示剩余12条评论

51
const int * ptr;

表示指向的数据是常量且不可变,但指针本身不是。

int * const ptr;

表示指针是常量且不可变的,但所指向的数据不是。


4
指向const的指针并不意味着指针所指向的对象是const。将指针定义为指向const只影响我们可以对指针做什么。 - user11748261

16

1) 常量指针:这种类型的指针是不能改变它们所指向的地址的。这意味着假设有一个指针指向一个变量(或存储该变量的地址)。现在,如果我们试图将指针指向其他变量(或尝试使指针存储其他变量的地址),那么常量指针无法实现此操作。

常量指针声明为:int *const ptr('const' 的位置使指针 'ptr' 成为常量指针)

2) 指向常量的指针:这种类型的指针不能改变它们所指向的值。这意味着它们不能改变它们持有地址的变量的值。

指向常量的指针声明为:const int *ptr('const' 的位置使指针 'ptr' 成为指向常量的指针)。

例子

常量指针

#include<stdio.h>

int main(void)
{
    int a[] = {10,11};
    int* const ptr = a;

    *ptr = 11;

    printf("\n value at ptr is  : [%d]\n",*ptr);
    printf("\n Address pointed by ptr  : [%p]\n",(unsigned int*)ptr);

    ptr++;
    printf("\n Address pointed by ptr  : [%p]\n",(unsigned int*)ptr);

    return 0;
}

现在,当我们编译上述代码时,编译器会抱怨:
practice # gcc -Wall constant_pointer.c -o constant_pointer
constant_pointer.c: In function ‘main’:
constant_pointer.c:13: error: increment of read-only variable ‘ptr’

因此,我们可以清楚地看到编译器抱怨我们无法更改常量指针所持有的地址。 指向常量的指针
#include<stdio.h>

int main(void)
{
    int a = 10;
    const int* ptr = &a;


    printf("\n value at ptr is  : [%d]\n",*ptr);
    printf("\n Address pointed by ptr  : [%p]\n",(unsigned int*)ptr);

    *ptr = 11;

    return 0;
}

现在,当上述代码被编译时,编译器会抱怨:
practice # gcc -Wall pointer_to_constant.c -o pointer_to_constant
pointer_to_constant.c: In function ‘main’:
pointer_to_constant.c:12: error: assignment of read-only location ‘*ptr’

因此,我们在这里也可以看到编译器不允许指向常量的指针改变被指向的变量的值。 引语

11

引用:This Thread

常量指针

首先让我们了解什么是常量指针。常量指针是一个指针,它不能改变其所持有的地址。换句话说,一旦一个常量指针指向一个变量,那么它就不能指向任何其他变量。

常量指针声明如下:
<指针类型> * const <指针名称>
一个示例声明如下:
int * const ptr;
下面是一个小代码示例,用于说明这些类型的指针:

#include<stdio.h>

int main(void)
{
    int var1 = 0, var2 = 0;
    int *const ptr = &var1;
    ptr = &var2;
    printf("%d\n", *ptr);

    return 0;
} 

在上面的例子中:

  • 我们声明了两个变量var1和var2
  • 声明了一个常量指针'ptr'并使其指向var1
  • 然后,将ptr指向var2。
  • 最后,我们尝试打印ptr指向的值。

指向常量的指针

从名称上可以看出,指向常量的指针是指不能更改它所指变量的值的指针。这种类型的指针可以改变它们所指的地址,但不能更改这些地址中存储的值。

指向常量的指针定义为: const <type of pointer>* <name of pointer> 例如: const int* ptr; 让我们来看一个简单的示例代码来说明指向常量的指针:

 #include<stdio.h>

int main(void)
{
    int var1 = 0;
    const int* ptr = &var1;
    *ptr = 1;
    printf("%d\n", *ptr);

    return 0;
} 

在上面的代码中:

  • 我们定义了一个值为0的变量var1
  • 我们定义了一个指向常量的指针,它指向变量var1
  • 现在,通过这个指针,我们尝试改变var1的值
  • 使用printf来打印新值。

通常我不会做家庭作业...不建议使用"url answers"啊,伙计...下次发答案而不是链接...虽然还是给你点赞了!! :) - NoobEditor
1
你应该提到这些是非编译示例,而不是正确使用的示例。 - MKaama

11
const int* ptr;

指向常量的指针(内容)。您可以修改指针。例如:ptr = NULLptr++,但不可能修改内容。

int * const ptr;

是一个常量指针。相反的情况也可能发生。您不允许修改指针,但您可以修改它所指向的内容,例如*ptr += 5


7
int i;
int j;

int * const ptr1 = &i;

编译器会阻止您更改ptr1
const int * ptr2 = &i;

编译器会阻止您更改*ptr2
ptr1 = &j; // error
*ptr1 = 7; // ok

ptr2 = &j; // ok
*ptr2 = 7; // error

请注意,您仍然可以更改*ptr2,但不能直接键入*ptr2
i = 4;
printf("before: %d\n", *ptr2); // prints 4
i = 5;
printf("after: %d\n", *ptr2); // prints 5
*ptr2 = 6; // still an error

您可以使用同时具有这两个特征的指针:

const int * const ptr3 = &i;

ptr3 = &j; // error
*ptr3 = 7; // error

关于“指向常量int”的非常好的澄清。不允许通过指针编辑“int”,但是可以通过其他方式编辑“int”。 - Alex

2

2

const int* ptr; 这里的意思是认为 *ptr 是常量,不能再次更改。

int * const ptr; 而这里的意思是将 ptr 视为常量,不能再次更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接