【问题标题】:Same address and not the same values with const与 const 相同的地址和不同的值
【发布时间】:2017-06-21 20:04:50
【问题描述】:

我在一个简单的 C 代码中发现了一点奇怪的东西。 实际上,我有 2 个变量,第一个是 const 变量,第二个是第一个变量的指针。

问题是,如果我打印这 2 个地址,它们是相同的,但如果我打印的值是不同的:

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

int                         main(void)
{
    bool const              b = true;
    bool                    *adr_b = (bool*)&b;

    *adr_b = false;
    printf("%p\n%p\n", &b, adr_b);
    printf("str = %d %d\n", b, *adr_b);

    printf("%p\n%p\n", &b, adr_b);
    return (0);
}

这怎么可能?

编辑

事实上,我知道这种行为是未定义的,但这是一个技术问题:如何一个地址可以存储 2 个不同的值?

【问题讨论】:

  • 所以你故意调用 undefined behavior 并想知道为什么你的代码表现得未定义? Leran 演员表的用途,如果您不完全了解演员表的作用,永远不要使用演员表!您告诉编译器不要抱怨,从而积极反对编译器。
  • 不要对格式感兴趣!代码很难阅读。
  • 如何一个地址可以存储 2 个不同的值?”——您错误地认为一个地址在这里存储了 2 个值。该程序具有未定义的行为(不止一次),因此完全无效。此外,当我在我的系统上编译并运行它(忽略警告)时,我得到str = 0 0 作为输出。未定义的行为是没有意义的。
  • 编译器可能决定它知道b不能改变(它是const),所以它不需要再次查看存储的值——它知道它必须是什么.它可能会决定它不知道adr_b 并查看内存。但这只是一种可能。任何结果都是有效的,因为代码具有未定义的行为。

标签: c pointers casting memory-address


【解决方案1】:

未定义的行为。您正在修改 const 变量。

C11 Standard Appendix J.2. Undefined behavior:

尝试通过使用具有非 const 限定类型 (6.7.3) 的左值来修改使用 const 限定类型定义的对象。

附录 J.2 虽然不是规范性的,但可以方便地找到标准中的实际规范性位置。 6.7.3 in paragraph 6 说:

6 如果尝试通过使用具有非 const 限定类型的左值来修改使用 const 限定类型定义的对象,则行为未定义。如果尝试通过使用具有非 volatile 限定类型的左值来引用具有 volatile 限定类型定义的对象,则行为未定义。133)


由于您尝试 - 并成功修改 - 通过使用具有非 const 限定类型 bool(此处为 *adr_b)的左值定义了具有 const 限定类型 (const bool b) 的对象,C 标准此后对程序的行为“没有要求”。有nasal demons

【讨论】:

  • 附注:附录 J 只是非正式的。它不是自动的。 (不过,它总结了其他章节中的信息,这些信息自动的。我并不是说它是错误的)
  • @Olaf ok ok... 引用 6.7.3。
  • 我对答案很好,只是我认为这个问题完全符合它的要求。一个不会无故添加演员表,所以我假设 OP 首先收到警告(“赋值删除const 限定符”或类似的),然后添加演员表“因为这样编译器不会抱怨,因此演员表修复了它” (我曾经从一个所谓的专业程序员那里得到过这个“借口”!)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
  • 2015-09-21
  • 2011-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多