Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在同一内存地址上有两个不同的值 代码 #包括 使用名称空间std; int main(){ 常数int N=22; int*pN=const_cast(&N); *pN=33; coutint*pN=const\u cast(&N); *pN=33;_C++ - Fatal编程技术网

C++ 在同一内存地址上有两个不同的值 代码 #包括 使用名称空间std; int main(){ 常数int N=22; int*pN=const_cast(&N); *pN=33; coutint*pN=const\u cast(&N); *pN=33;

C++ 在同一内存地址上有两个不同的值 代码 #包括 使用名称空间std; int main(){ 常数int N=22; int*pN=const_cast(&N); *pN=33; coutint*pN=const\u cast(&N); *pN=33;,c++,C++,您的代码调用未定义的Behavior1,因为您正在修改const限定变量/对象的内容 (一) 未定义的行为:在使用 错误的程序结构或错误的数据,对此 本标准无任何要求。[注:允许的未定义行为 范围从完全忽略情况到不可预测 结果,在翻译或程序执行过程中在 记录环境特征的方式(有无) 发出诊断消息),以终止翻译 或执行(发出诊断消息) 为什么在同一地址有两个不同的数据 #include <iostream> using namespace std; int main() { c

您的代码调用未定义的Behavior1,因为您正在修改
const
限定变量/对象的内容

(一) 未定义的行为:在使用 错误的程序结构或错误的数据,对此 本标准无任何要求。[注:允许的未定义行为 范围从完全忽略情况到不可预测 结果,在翻译或程序执行过程中在 记录环境特征的方式(有无) 发出诊断消息),以终止翻译 或执行(发出诊断消息)

为什么在同一地址有两个不同的数据

#include <iostream>
using namespace std;

int main() {
    const int N = 22;
    int * pN = const_cast<int*>(&N);
    *pN = 33;
    cout << N << '\t' << &N << endl;
    cout << *pN << '\t' << pN << endl;
}
没有。编译器可以优化任何提到的常量,就像您在其中编写了它的编译时值一样


请注意,如果您执行了诸如写入为常量保留的内存之类的恶作剧,编译器也可以在运行硬盘时生成擦除硬盘的代码。

通过声明
N
为常量,您已经承诺不会修改它。然后您就去修改它。这打破了编译器的一个假设,结果,程序的行为不正确


这被称为“未定义的行为”-在违反语言中的假设后,程序的行为是完全未定义的。它不必产生该输出-它可以同时产生
33
,或
42
,或崩溃,或擦除硬盘,或通过鼻腔召唤恶魔。因此,不要修改常量值:)

const\u cast in您的代码,只需将一个指针“Pn”交给“N”,通过该指针可以修改“N”。N的地址与交给的指针“Pn”保持不变。

您在第
*Pn=33;
行上得到未定义的行为,因为您正在修改常量值。任何情况都可能发生。不要这样做


不过,您的编译器很可能只是进行了优化。行中:

int * pN = const_cast<int*>(&N);
*pN = 33;

在下一行中,获取地址
N
处的值,将其“设置”为33。(但实际上,您所做的只是删除有关程序状态的任何保证。)

您可以将N声明为volatile,以强制编译器从变量的内存位置获取当前值

volatile const int N=22;

我也有同样的问题()。我想大家在这里都回答得很好。只需添加编译器的程序集输出

这是我的原始代码

cout << 22 << '\t' << &N << endl;
const int y=7;
int*a=新的int;
a=常数(y);
*a=8;

std::cout Downvoting,因为您没有回答最初的问题,即当使用不同的方法读取相同的内存地址时,为什么编译器输出两个不同的值。我同意这是可能的原因。查看生成的机器代码可以验证这一点。可能有一条
push 0x16
指令用于E>代码>在那里执行“<代码> 5=3 < /COD> >的语言是非常危险的事情。在C++中,必须编写代码> COSTYSTCAST(STATICE-CAST(5))=3
。它表达了同样的荒谬,也同样危险,但至少它在路上设置了障碍。永远不要使用
const\u cast
const\u cast
的目的是从实际上不是
const
的事物中去除const。有一些简单的例子。@thb:栗子的意思不是to描述一个可能的场景,而不是指出可能的未定义行为的规模;这是一种方便的方式,可以说真的,字面上任何事情都可能发生。你愿意,比如,“允许未定义的行为将私有变量的内容写入屏幕内存*?因为我编写的程序意外地覆盖了常量内存。@thb:或者,“未定义的行为可能导致web浏览器安全策略停止工作,并允许任意恶意代码在浏览器中运行”因为我也引起了这个错误。我们需要一些方法来描述它能得到多坏。你喜欢什么?我最后的评论没有回答你的问题。回答:我希望你给出的答案完全正确,因为这是你的答案。如果你和我在一起,和一个C++初学者在一起,我可能会添加到你的广告中。我的观点是,用未定义的行为(UB)进行实验可以在不暴露于网络中的敌对行为的环境中,使好奇的程序员陶醉。C++标准几乎不说为什么会出现SeGebug(而不是其他UB)。例如,可能会出现分段错误的探索,但这只是在教育中。只是不在生产中。@哦,完全在实验中可以对实现细节产生洞察力。但是从这一经验中可以学到很多东西。我看到这里的问题基本上是问“为什么我没有C++ Sebug”。知道一个实现在你做坏事时崩溃不应该给其他实现一种不劳而获的安全感。过度概括当你做坏事时发生的最糟糕的事情是崩溃,就像C#或Java一样,这会导致低估可能的后果。@thb:另外,你注意到C是“面向硬件",我也同意,但认为所有C实现都会有直接的、不令人惊讶的未定义行为的后果,这是假设优化策略在20世纪70年代就停止了。我最喜欢的关于现代编译器中UB后果的文章是——Raymond指出UB会导致效果在时间上向后移动.这是一种可能的行为
cout << 22 << '\t' << &N << endl;
const int y = 7;
int* a = new int;
a = const_cast<int*>(&y); 
*a = 8;
std::cout << (int)*(&y) << std::endl;
std::cout << (int)*(&y) << std::endl;
00381CB6  push        offset std::endl<char,std::char_traits<char> > (03813C5h)  
**00381CBB  push        7**  
00381CBD  mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (03900ACh)]  
00381CC3  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03900B8h)]  
00381CC9  mov         ecx,eax  
00381CCB  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03900BCh)]