首页 > 试题广场 >

下面程序的输出结果是多少?

[单选题]
在c++中,
const int i = 0; 
int *j = (int *) &i; 
*j = 1; 
printf("%d,%d", i, *j)
输出是多少?
  • 0,1
  • 1,1
  • 1,0
  • 0,0
这个题一定要注意是在C++中的运行结果。
在C语言中
void main(){
	const int i = 0;
	int *j = (int *)&i;
	*j = 1;
	printf("%d,%d", i, *j);
	system("pause");
}
结果输出为1,1
在C++中
#include<iostream>
using namespace std;
int main(void){
	const int i=0;
	int *j = (int *)&i;
	*j = 1;
	printf("%d,%d", i, *j);
	system("pause");
	return 0;
}
结果输出为0,1
分析:C语言中的const是运行时const,编译时只是定义,在运行才会初始化。C语言中const变量不能用于成为数组长度等作为编译时常量的情况,原因就在此。C语言const变量在运行时改变了是可以再次读出改变后的值的。
C++中,const变量是编译时的常量,可以向#define定义的常量一样使用。故C++中const变量的值在编译时就已经确定了,直接对cosnt变量进行了值的替换,因此当const变量的值改变时,const的变量值是不会得到更新的。
这几行代码在C和C++中都会改变const变量的值,只不过C++中const变量在编译的时候已经确定了,而C中的const变量可以在运行时改变后再次读取。以下代码核实了C++中的const变量确实被改变了。
#include<stdio.h>
#include<iostream>
using namespace std;
int main(void){
	const int i=0;
	int *j = (int *)&i;
	*j = 1;

	printf("%d,%d\n", i, *j);
	cout << "i address"<<&i << endl;
	cout << "j address"<<j << endl;
	
	return 0;
}
同一个地址,即同一个变量。C++中const变量确实别改变了。i的值没有更新而已。
发表于 2015-08-14 22:09:31 回复(12)
唔,感觉都没有说到重点。这跟编译器的优化编译有关。
C++中的常量折叠:指const变量(即常量)值 放在编译器的符号表中 ,计算时编译器直接从表中取值,省去了访问内存的时间,从而达到了优化。
具体可以看这个:
http://blog.csdn.net/heyabo/article/details/8745942

发表于 2015-08-18 17:16:51 回复(13)
c语言中const只是指定这个变量是只读的,并非真正意义上的常量,并且可以通过指针修改。c++中常量都会有一张常量表,任何对常量的读取都是从这个表里直接读取,而通过指针进行修改,修改的是常量在栈上对应地址空间的内容,本身常量表里的内容不会被改变
发表于 2016-10-04 17:26:32 回复(1)
编译器只对const变量的值读取一次。所以打印的是0
发表于 2015-08-13 16:13:52 回复(5)

C++ const 看做常量,编译器会使用常数直接替换掉对 i 的引用,例如 cout<<i; 会理解成 cout<<10; 并不会去访问 i 的内存地址去取数据,这里有点像是 C 语言里的宏 #define i 10 。因此 C++ i 会输出 10 ,而 *j 会输出 20. 

发表于 2015-11-29 17:27:16 回复(0)
const int i = 0; 
int *j = (int *) &i; 
*j = 1; 
printf("%d,%d", i, *j);
以上代码在C语言中编译结果为:
        movl    $0, 24(%esp)        //const int i=0
        
        leal    24(%esp), %eax      //int *j=(int*)&i; 
        movl    %eax, 28(%esp)
        
        movl    28(%esp), %eax    //*j=1
        movl    $1, (%eax)

        movl    28(%esp), %eax  //这两条语句的作用是
        movl    (%eax), %edx //将*j的值加载到edx 寄存器
        
        movl    24(%esp), %eax //将i的值加载到eax寄存器,注意此处
        
//printf函数调用,参数逆序入栈
        movl    %edx, 8(%esp) //*j的值入栈
        movl    %eax, 4(%esp) // i的值入栈,注意此处,和C++进行比较
        movl    $.LC0, (%esp)
        call    printf

在C++语言中为:
        movl    $0, 24(%esp) //const int i=0
        
        leal    24(%esp), %eax // int *j=(int*) &i;
        movl    %eax, 28(%esp)

        movl    28(%esp), %eax // *j=1
        movl    $1, (%eax)

        movl    28(%esp), %eax //这两条语句的作用是将
        movl    (%eax), %eax //*j的值加载到eax寄存器
//printf函数调用参数逆序入栈
        movl    %eax, 8(%esp) // *j的值入栈
        movl    $0, 4(%esp)  //0入栈,注意此处和C提醒注意的地方进行比较
        movl    $.LC0, (%esp) //%d,%d入栈
        call    printf
为什么在提醒注意的地方C语言中入栈的是i的值,C++中入栈的是0的值呢?
这和const在两种语言的语义有关,
在C语言中,除了你不能通过直接赋值(例如i=100)来改变const修饰的量的值以外,const修饰的量与普通变量没有差别。
在C++语言中,const修饰的量可视为具有类型的#define 宏定义,在汇编阶段,引用到const修饰的量的地方会直接以值替换掉。
正式这种原因造成了上面需要注意的地方在C和C++中的不同。
所以在C++中答案为A
发表于 2015-08-19 18:27:05 回复(1)
在C语言中,const变量只不过是修饰该变量名,它并不能使内存变为只读。也就是说,我们不能通过变量名再去操作这块内存。但是可以通过其它方法,如指针,通过指针是可以修改被const修饰的那块内存的
发表于 2019-06-26 18:17:51 回复(0)
寄存器变量和内存变量 主要还是为了优化
如果为volatile const int i = 0; 就会强制从内存取值,结果就为11了
发表于 2015-09-06 16:02:28 回复(1)
http://blog.chinaunix.net/uid-26853826-id-3365403.html
发表于 2015-08-14 18:20:38 回复(0)
这一题是要看编译器的
发表于 2015-08-14 14:28:26 回复(0)
编译器只对const变量的值读取一次。所以打印的是0。i实际存储的值发生了改变。但是为什么能改变呢,从其存储地址可以看出来,其存储在堆栈中。
发表于 2015-08-13 21:35:06 回复(0)
c中const随时更新,C++则不更新
发表于 2018-07-03 23:53:28 回复(0)
const int i = 0;
放到一个符号表中,值是无法修改的。在C++中,当对 i 取地址时,为了兼容C,会给 i 分配一个内存空间,并且值为0,同时也可以修改里面的值。
发表于 2017-08-08 15:45:12 回复(0)
constinti = 0; //这句才是重点。不可修改
int*j = (int*) &i; //将0的地址赋予指针运算的
*j = 1; //在0的地址下赋予1
printf("%d,%d", i, *j)//结果是i=0,j=1
发表于 2015-09-13 17:07:06 回复(0)
对于这一题确实没注意过!
而且这里的解释好牛的说!!!

也就是说编译器处理const常量只读取一次就将其存入符号表,而对内存的操作并不影响其值。
编辑于 2015-09-05 20:01:00 回复(0)
cpp 中 const 的值编译时确定
发表于 2024-08-13 07:56:13 回复(0)
const变量放在了符号表中,尽管const变量值发生了变化的,但是在打印i的时候编译器从符号表中取值,不会影响
发表于 2024-05-09 18:46:05 回复(0)
请问(int *) &i和i有什么区别?
发表于 2023-07-16 11:03:30 回复(0)

补充一下答案,如果使用volatile关键字,就会输出1,1

int main() {
    volatile const int i = 0;
    int* j = (int*)&i;
    *j = 1;
    printf("%d,%d", i, *j);
    return 0;
}

volatile关键字告诉编译器不要对变量i进行优化,每一次读取i的值都必须从内存中读取,而不是读取符号表

发表于 2022-04-01 08:54:08 回复(0)
这道题笔试过
发表于 2021-11-20 09:39:26 回复(0)