为啥通过指针分配给常量没有效果? [复制]

Posted

技术标签:

【中文标题】为啥通过指针分配给常量没有效果? [复制]【英文标题】:Why does assigning to a constant via pointer have no effect? [duplicate]为什么通过指针分配给常量没有效果? [复制] 【发布时间】:2017-08-22 16:18:35 【问题描述】:

在下面的示例中,“ptr”指向常量变量“local”。为什么通过分配'*ptr'修改'local'不会改变'local'的值?

#include <stdio.h>
int main(void)

    const int local = 10;
    int *ptr = (int*) &local;

    printf("address of local: %p \n", &local);
    printf("value of ptr: %p \n", ptr);
    printf("Initial value of local : %d \n", local);
    printf("Initial value of *ptr : %d \n", *ptr);

    *ptr = 100;
    //*((int*)&local) = 1000;

    printf("Modified value of local: %d \n", local);
    printf("Modified value of *ptr: %d \n", *ptr);
    printf("address of local: %p \n", &local);
    printf("value of ptr: %p \n", &(*ptr));

    return 0;

输出:

address of local: 0x7ffd946bd9c4
value of ptr: 0x7ffd946bd9c4
Initial value of local : 10 
Initial value of *ptr : 10 
Modified value of local: 10 
Modified value of *ptr: 100 
address of local: 0x7ffd946bd9c4 
value of ptr: 0x7ffd946bd9c4

【问题讨论】:

因为丢弃***const 对象的const 是未定义的行为。 @nwp 实际上,这并不完全正确,演员表本身不是 UB。实际修改的只有UB。一般来说,C++ 中的指针强制转换很少会直接导致 UB(我确信有例外)。它通常是 UB 的错误转换指针的 用法 如果你说某个东西是 const,它取决于编译器如何处理它。据你所知,它被放在只读存储器的某个地方,因为你说过你不会改变它。现在你正在尝试编辑它。你为什么希望它改变? const 在很多情况下根本就没有地址(直接值 10 用于机器码) 谢谢大家:)。现在我明白了。 【参考方案1】:

行:

*ptr = 100;

是未定义的行为。原因是因为ptr 指向一个const 对象。您通过抛弃 const 来进行编译,但该语言仍然说实际修改声明为 const 的对象是非法的:http://en.cppreference.com/w/cpp/language/const_cast。

未定义行为的存在基本上意味着您的程序可以在不同的编译器/优化级别上执行许多不同的、奇怪的事情。简而言之,不要修改const 对象,暂时避开const_cast。这通常是糟糕设计的标志;它的合法用途相对较少,您将在学习过程中学习。下面是一个罕见的有效使用 const_cast 示例的链接:How do I remove code duplication between similar const and non-const member functions?。这种技术消除了代码重复,但从根本上说,它依赖于在只有 指针 是 const 限定的情况下丢弃 const-ness,但已知底层对象不是 const。

实际const 值与const 别名指针/引用之间的区别在C++ 中非常重要。

【讨论】:

谢谢,尼尔弗里德曼。我会接受你的回答。 @HeChen - 这是明智的:p【参考方案2】:

此声明:

   int *ptr = (int*) &local;

紧随其后

   *ptr = 100;

错了。标准将这种类型的行为(通过与赋值目标类型不匹配的指针赋值)称为“未定义行为”,这意味着编译器不需要产生警告消息(如果它会很好确实),但这也意味着编译器不需要生成按照您期望的方式实现语句的代码。

您可以阅读有关未定义行为和相关语言问题的更多信息here

【讨论】:

不,这个答案是错误的,演员表本身不是UB。只有作业是。 抛弃 const 不是 UB,有时必须使用一些遗留的 C 接口来完成。在你抛弃 const 之后修改值是。 你是对的,当然。我试图简化。

以上是关于为啥通过指针分配给常量没有效果? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

尝试从常量 char * 类型的指针复制数据时出现“超出内存访问”错误。为啥?

为啥传递给函数的指针的值没有改变? [复制]

C语言指针变量为啥要赋初值?

c语言常量指针赋值给变量指针导致警告

为啥没有给另一个进程访问内存位置的权限?

为啥通过切片分配到列表末尾之后不会引发 IndexError? [复制]