首页 > 试题广场 >

以下程序输出是____

[单选题]
对于以下C++程序代码输出是____。
#include <iostream> 
using namespace std; 
int main(void) 
{ 
    const int a = 10; 
    int * p = (int *)(&a); 
    *p = 20; 
    cout<<"a = "<<a<<", *p = "<<*p<<endl; 
    return 0; 
} 
  • 编译阶段报错运行阶段报错
  • a = 10, *p = 10
  • a = 20, *p = 20
  • a = 10, *p = 20
  • a = 20, *p = 10
推荐
因为a 和p都指向相同的内存地址,所以输出的前两个结果是相同的,但为啥相同的内存里的结果不相同么?--这就是常量折叠.

这个"常量折叠"是 就是在编译器进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。可以算作一种编译优化。

因为编译器在优化的过程中,会把碰见的const全部以内容替换掉(跟宏似的: #define pi 3.1415,用到pi时就用3.1415代替),这个出现在预编译阶段;但是在运行阶段,它的内存里存的东西确实改变了!!!
简单的说就是,当编译器处理const的时候,编译器会将其变成一个立即数。
编辑于 2015-06-19 17:25:55 回复(9)
其实这道题真正的答案是不确定的,他与编译器有关,在C++标准中并没有强制规定将一个const 常量转换为一个非const后应该怎么办,这个是交给编译器设计者来决定的,以VS为例子,如果建立的是.c文件,也就是在纯c的环境下编译该代码,输出的结果将会是20 20,但是如果是C++则是10,20。它真正的处理原理如下,a作用域下在C++中所有的常量a在预编译阶段就已经做了类似于宏替换的工作,所以输出的是它的常量值,但是如果你进去调试就会发现变量a的地址与p地址相同,且p指向的地址的内容已经修改为了20,也就是说其实我们对这部分地址的内容已经做出了修改,所以*p输出的是20。但是在纯C的环境下,它并没有类似于宏替换的那一步,所以它输出的就是修改后的值。
编辑于 2015-08-12 17:14:33 回复(14)
a = 10, *p = 20 因为使用const 编译器会优化,对于以后见到a ,编译器立马用10替代. 而p是新定义的一个指针变量,开始p通过 int *p = (int *)(&a); 获得了栈区常量a的地址.即p指向这个地址,但是因为const 导致编译器优化,直接在符号表中 用10代替a了,所以导致 打印a还是10,而打印那个内存单元的地址就变成了 20
发表于 2015-04-29 22:43:54 回复(7)
const变量在编译期会被编译期编译成一张常量表,所有读取常量的操作都会从这个常量表里直接读取,因此输出c永远都是10,但是c本身又是一个局部变量,那他会不会在栈上分配空间呢,答案是当对常量使用取地址&操作给某个指针赋值或者使用extern声明时才会在栈上分配内存空间,并且通过指针的操作都是对栈上的空间进行操作,对常量表的内容不会有任何影响,因此*p是20;
发表于 2016-10-11 14:21:41 回复(6)
高票回答实际上是有很大问题的。实际上这个替换发生在编译阶段,而不是预编译阶段(宏定义的替换发生在预编译阶段),但const变量的值实实在在存储在了.rodata区,当使用p取地址引用时,才会a分配了内存,并从.rodata区中将a地值复制到了p所指向的内存中,当使用p引用该内存中的值的时候输出的就是内存中p修改的值,而对a的输出,当然也就是编译时替换的值(也就是所谓的常量折叠)
参考:
http://notes.maxwi.com/2016/06/05/source-to-program/
http://notes.maxwi.com/2016/06/11/cpp-memory-layout/
发表于 2016-08-21 14:49:55 回复(2)
编译器优化,每次看到a就直接取10,不再从a所在的内存地址内取值了
发表于 2015-04-11 13:03:03 回复(0)
const的变量在特定情况下可以通过指针修改,但是在另一些情况下是不能通过指针修改的。
1.可修改的情况

#include <iostream> void main() {  
  int const a = 10;  int *p = (int*)&a;  *p = 20;   cout<<"&a="<<&a<<endl;   cout<<"p="<<p<<endl;   cout<<"a="<<a<<endl;   cout<<"*p="<<*p<<endl;  } 
程序能正常运行,且常量被修改了,但是有一个问题:
   为什么 printf(" a=%d\n", a); 打印a=10?
难道一个地址空间可以存储不同的俩个值,当然不能,这是因为a是const变量,编译器对a在预处理的时候就进行了替换。编译器只对const变量的值读取一次。所以打印的是10。而指针p是对该存储空间的值进行了修改。
2.不可修改的情况
VC6编译器环境下不可修改。

详细讲解参考博客:http://blog.chinaunix.net/uid-26853826-id-3365403.html

编辑于 2016-06-26 22:10:38 回复(0)
选D,a的值是改变了,和*p一样是20,但是编译器碰到a就直接替换成10了。
发表于 2015-04-12 00:08:03 回复(4)
int * p = (int *)(&a);就是因为a是const
发表于 2015-06-03 21:24:18 回复(0)
Copy on write?
发表于 2015-08-16 13:49:37 回复(0)
D *a和*p都指向同一个地址 并且中间的过程 a的值发生了改变 但是const int a=10 让编译器一遇见a就会输出10  
发表于 2015-04-12 13:45:25 回复(3)
几个知识点:
1、const变量会在编译阶段替换成对应的常量,类似define,但是和define不同的是,define是在预处理阶段替换的,而且const有类型检查。
2、有的人说用volatile可以改变a为20,其实volatile(adj.易变的)的作用就是取消编译器优化,并且每次读取这个变量的值都从原来的地址上读取,而不是从寄存器上读取。
编辑于 2019-07-12 13:17:49 回复(0)
vs2015中运行结果是10和20,
但是调试结果中使*p=20的时候,a中的内容会立即变成20,但是因为const修饰了a,所以a会被编译器用10去替代,所以最终结果是10和20,如果此时再取a地址中保存的值,结果就会是20,但是只要你直接输出a,那么结果依旧是10,不会变的

编辑于 2018-03-16 14:10:28 回复(0)
这道题的答案和编译器有关,在vs下运行,结果是10,20,在gcc下运行结果是20,20。因为在vs下限制了这种操作。
对于const int a=10来说,其值是不能修改,但可以通过指针来修改。
发表于 2016-07-02 09:20:16 回复(0)
如果用voliate关键词修饰a会怎样?
发表于 2023-11-24 14:51:25 回复(0)
这应该算cpp编译过程当中的bug吧,不应该检查一下这个地址的变量允不允许修改吗?
发表于 2023-03-21 15:38:29 回复(0)
虽然各位大佬的解释看不懂 但大概明白就是const类型的值被存了起来 取的时候直接取

就算通过*p修改了值,输出a的时候还是10
发表于 2023-03-21 10:23:26 回复(0)
a=10,*p = 20
发表于 2021-11-01 16:35:01 回复(0)
<p>cpnst是常量</p>
发表于 2021-01-16 16:58:10 回复(0)
亲自复制代码跑了一下,选C
发表于 2019-04-28 17:11:19 回复(0)
C++中const常量类似于宏定义,用到的时候不到内存取值;C中没有这种优化,每次用到还要到内存取值
发表于 2018-03-09 09:27:46 回复(0)