整型指针指向常量整型

4

我想知道内部发生了什么,以及它与显示的值的关系。

代码如下:

# include <iostream>

int main(){
    using namespace std;
    const int a = 10;

    int* p = &a;  //When compiling it generates warning "initialization from int* to 
              //const int* discard const -- but no error is generated

    cout << &a <<"\t" << p <<endl; //output: 0x246ff08 0x246ff08 (same values)
    cout << a << "\t" << *p << endl; //output: 10 10

    //Now..
    *p = 11;
    cout << &a <<"\t" << p <<endl; //output: 0x246ff08 0x246ff08 (essentially, 
                               //same values and same as above, but..)
    cout << a << "\t" << *p << endl; //output: 10 11

    return 0;
}

问题: 如果p = a的地址, 那么a = 10, 但是*p = (跳转到a的地址并读取内存位置中的值) = 11,这是怎么回事?


9
你欺骗了编译器,现在抱怨编译器欺骗了你。自食其果。 - Kerrek SB
@user 既然你无法接受Kerrek的评论,那么你应该接受ouah的答案。 - David Heffernan
但不会生成错误。有时候记住实现不需要为格式不正确的程序发出错误;它只需要发出诊断(除非另有规定),在这种情况下它确实发出了诊断。然而,编译和运行格式不正确的程序是允许的。例如,如果您想使用一个旧的C库例程,该例程接受指向非const char的指针但实际上不修改指针,则这是可取的。如果您希望编译器执行更严格的限制,请考虑至少使用-pedantic-Werror - Stuart Olsen
这很尴尬...实际上我已经不再从事C++方面的工作了,所以我离开了这个问题。此外,我也不确定我的安装或旧版本是否有问题,因为大多数答案都建议这种行为“不应该”发生,所以我真的不知道原因是什么。 - user3272925
4个回答

8
 cout << a << "\t" << *p << endl; //output: 10 11

你欺骗了编译器,它报复了你。
使用:
const int a = 10;

你承诺永远不会修改a对象。


5
你承诺不修改 a,编译器相信了你。所以它决定优化掉对 a 的读取,因为它信任你。你打破了你的承诺。
话虽如此,真正的C++编译器不会编译你的代码,因为 int* p = &a 是非法的。所以也许你在说谎。或者你需要一个真正的C++编译器。

1
有趣的事实:编译器通常会哭着入睡。 - JustSid
...并被自己的尖叫声惊醒。 - Captain Obvlious
请帮我看看这段代码,我自己也被搞糊涂了。虽然这只是一小段代码,但我已经检查过它的乘法运算了。能否请您尝试一下并检查结果?也许是因为我正在使用一个奇怪的编译器!顺便说一句,当使用引用而不是指针时,结果相同。 - user3272925
代码不应该编译。这是非法的。我的编译器不会编译它。你的编译器很糟糕。如果它确实编译了,那么你欺骗了编译器关于aconst的事实,正如Kerrek SB所说,“种瓜得瓜,种豆得豆”。是时候换一个更好的编译器了。你在使用Turbo C++吗? - David Heffernan

2

就像Ouah所说编译器已经开始反击了,

但我不同意你的观点,认为它并没有完全没有报错。

const int a = 10;

int* p = &a;

您不能将常量赋值给非常量指针。

@Mooing Duck - 警告?那么“const”的作用是什么? - Hamza
如果是这样的话,我想我们就不需要 const_cast 了。问题中的代码不是有效的 C++。 - David Heffernan
只是好奇,我记得看到过类似的问题,我认为这是未定义的行为。不是吗? - user1508519
同意David的观点。const被引入是因为它对程序员比C预处理器#define有优势,因为编译器本身可以理解和使用它,所以当更改时可以给出错误提示。我认为你在这里搞混了概念,如果他们能够加入警告,那么当添加新关键字时就可以将其作为错误处理。 - Hamza
你听说过Visual Studio吗? - Hamza
显示剩余11条评论

0

在 C 中,这是未定义行为。在 C++ 中,这将无法编译。David Heffernan 多次重复过这句话,但值得再次强调。这是现代编译器应该出现的错误:

main.cpp:7:10: error: cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'

    int* p = &a;  //When compiling it generates warning "initialization from int* to 

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