为什么指向const的指针所指向的位置可由其他变量赋值?

时间:2017-08-19 19:33:00

标签: c pointers

我写了这段代码

#include <stdio.h>
int main() {
     int b = 15;
     const int *foo = &b;
     //b = 20;
     *foo = 20;
     printf("%d", *foo);
     return 0;
}

这意味着foo指向的位置无法更改。这意味着b无法改变。但是当我取消注释行b = 20时。它没有显示任何错误,我得到输出20。在这段代码中我得到了这个错误

main.c: In function 'main':
main.c:15:10: error: assignment of read-only location '*foo'
      *foo = 20;

如果*foo b是只读位置,为什么我可以更改其值b = 20

5 个答案:

答案 0 :(得分:7)

什么是

 int b=15;
 const int* foo=&b;   

意思?

这意味着,

  • b是一个可修改的int对象。
  • &b的类型为int *foo的声明会将&b转换为const int *类型。这是有效的资格转换。
  • {li> int foo指向的对象不得使用foo进行修改。

上述资格转换不会使b的声明无效,即它仍然是可修改的b仍可用于更新其值,但*foo无法使用。

const视为承诺。您向编译器承诺,您不会更改foo指向的位置的值,但是没有人阻止您通过其他方式更改该位置的值来打破该承诺。

答案 1 :(得分:7)

我认为chqrlie是正确的,当他说错误消息“只读位置'* foo'的分配”是误导性的。实际上,const int *foo(即定义为指向const int的指针)并不意味着指针所寻址的内存本身就是不可变的;它只是意味着指针寻址的内存不能通过此指针更改;但是,它可能会以其他方式改变。您可以定义,例如第二个指针int *foo2 = &b,您可以通过该指针更改foo2寻址的值。

因此,您可能会将指针视为与特定内存地址的值的单独视图,并且可以将视图声明为只读。但是,这不会影响特定内存地址本身的值是否不可变:

int main()
{
    int b=15;  // b is mutable
    const int* foo=&b; // *foo is immutable; b remains mutable
    int *foo2=&b; // *foo2 is mutable
    b=20;  // allowed, since b is mutable
    *foo=20; // not allowed, since "*foo" is immutable, even if the value to which it points (i.e. b) would be mutable
    *foo2=20; // allowed, since "*foo2" is mutable

    return 0;
}

虽然没有被问到,反过来说,你实际上可以将定义为不可变的,然后不得以任何方式改变这个值;如果以某种方式通过写入其内存地址来操纵该值,则行为未定义:

const int c = 15; // c is immutable
int* bar = &c; // warning: discards const qualifier
printf("%d\n", c);
*bar = 20;  // undefined behaviour from here on; modifying a const value is not allowed.
printf("%d\n", c); // undefined behaviour; good chance that it still prints 15, because a compiler might have relied on the fact that c is 15 and immutable
printf("%d\n", *bar); // undefined behaviour; probably printing 20?

希望它有所帮助。

答案 2 :(得分:3)

不,const int* foo = &b;并不意味着您无法更改b,这意味着您无法取消引用此指针并更改取消引用指针的值,就像这样

*foo = 20;

你不能用const说某些内存对所有人来说都是无法修改的。你可以说只有const变量才能改变这段内存,所以这个操作(如果b没有const修饰符)完全有效,即使你有指针指向{{ 1}}。

b

答案 3 :(得分:0)

如果你想要一个不是常量对象的常量指针声明它:

 T * const ptr = &t

其中T是对象的类型,t是对象本身

答案 4 :(得分:0)

这个问题的答案是在将指针声明为

之后
const int *foo = &b;

你不能将* foo用作L值,因为此代码也会出现相同的错误

#include <stdio.h>
int main() {
     int a=10,b = 15;
     const int *foo = &b;
     foo=&a; //assigning foo the address of a
     *foo=30; // Again here you cant use *foo
     printf("%d", *foo);
     return 0;
}