(转)const变量通过指针修改问题

程序笔试题-const变量通过指针修改问题 2012-10-06 20:45:18

分类: C/C++

const的变量在特定情况下可以通过指针修改,但是在另一些情况下是不能通过指针修改。

以下是VC6下才测试。

1 不能修改的情况

#include <stdio.h>
int const a = 10;
void main(void)
{
 int *p = (int*)&a;
 *p = 20;
 printf("%d\n", *p);
}

程序编译通过,但运行时错误:

指示a存储的空间不可以写,也就是没有写权限,不能修改其值。估计是存储在全局空间,且只有可读属性。

2 能修改的情况

#include <stdio.h>
void main(void)
{
 int const a = 10;
 int *p = (int*)&a;
 *p = 20;
 printf("&a=%d\n", &a);
 printf(" p=%d\n", p);
 printf(" a=%d\n", a);
 printf("*p=%d\n", *p);
}

程序能正常运行,且常量被修改了,但是有一个问题:

为什么 printf(" a=%d\n", a);

打印a=10?

难道一个地址空间可以存储不同的俩个值,当然不能,哈哈,这是因为a是const变量,编译器对a在预处理的时候就进行了替换。编译器只对const变量的值读取一次。所以打印的是10。a实际存储的值发生了改变。但是为什么能改变呢,从其存储地址可以看出来,其存储在堆栈中。

验证如下:

#include <stdio.h>
void main(void)
{
 int const a = 10;
 int b = 20;
 int *p = (int*)&a;
 *p = 20;
 printf("&a=%x\n", &a);
 printf("&b=%x\n", &b);
 printf(" p=%x\n", p);
 printf(" a=%d\n", a);
 printf("*p=%d\n", *p);
}

变量a和b的地址相近。

总结,const全局变量存储在全局存储空间,其值只有可读属性,不能修改;

const局部变量存储在堆栈中,可通过指针修改其值;

const变量在预处理是处理,编译器只对其值读取一次。

知乎上回答

const在C语言中是表示道义上保证变量的值不会被修改,并不能实际阻止修改,通过指针可以修改常变量的值,但是会出现一些不可知的结果。几种情况不同,我们一个一个来看。

1、直接赋值

const int a = 3;
a = 5;
// const.c:6:2: error: assignment of read-only variable ‘a’

这种情况不用多说,编译错。

2、使用指针赋值,@孙健波提到的方法,在gcc中的warning,g++中出现error,是因为代码写得不对,由非const的变成const不用显式的转换,const变为非const需要显式转换,这种情况应当使用显式的类型转换。

const int a = 3;
int* b = (int*) &a;

printf("a = %d, *b = %d\n", a, *b);
*b = 5;
printf("a = %d, *b = %d\n", a, *b);

运行结果(注:使用msvc编译的结果一致):

$ gcc const.c
$ ./a.out
a = 3, *b = 3
a = 5, *b = 5

$ g++ const.cpp
$ ./a.out
a = 3, *b = 3
a = 3, *b = 5

这里使用g++编译时,a的值之所以没有改变,是因为编译时a是常量,然后被编译器编译为立即数了。因此对使用b指针修改不会更改a的值。

值得注意的是,如果a被定义为全局常变量,使用指针修改会引发segment fault。

在函数的原型中,我们也常用const修饰指针,表示函数的实现者在道义上不会去修改这个指针所指向的空间。例如我们熟知的strcpy函数,原型如下:

char* strcpy(char* dst, const char* src);

传入的参数src类型是const char*,表示函数内部实现不会修改src所指向的空间。之所以说是道义上,是因为在内部通过上述指针强制类型转换的方式可以修改该空间的值。另外,如果我们声明了我们不会修改传入指针的所指向的空间,那么我们也不应当去修改这块空间,因为这个传入的指针可能会是一个不可写的内存,然后出现段错误。

时间: 2024-10-11 00:46:19

(转)const变量通过指针修改问题的相关文章

const与指针修改const对象

我们都知道const对象作用是声明变量为常量,在程序中除非显示转换,否则无法修改. 本文针对显示修改的情况,提醒了一种隐式的错误,以及解决办法. 考虑下面的代码: #include<iostream> int main(){ const int a=0; int *p=const_cast<int*>(&a);//&a返回int *,const_cast<int*>显示转换为int*. *p =1; int b=*p; int c=a; std::cou

c++中的const参数,const变量,const指针,const对象,以及const成员函数

const 是constant 的缩写,“恒定不变”的意思.被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性.所以很多C++程序设计书籍建议:“Use const whenever you need”. 1.用const 修饰函数的参数 如果参数作输出用,不论它是什么数据类型,也不论它采用“指针传递”还是“引用传递”,都不能加const 修饰,否则该参数将失去输出功能.const 只能修饰输入参数: 如果输入参数采用“指针传递”,那么加const 修饰可以防止意外地

c++ ,const对象中的变量不能被修改

const对象中的变量不能被修改,即使const对象中的函数也不能修改该对象中的变量值 #include <iostream> using namespace std; //----------------------------------------------- class Test { public: int x; Test(); void change(int a); }; Test::Test() { this->x = 23; } void Test::change(int

C/C++ const变量的修改

C语言中的const是运行时const,编译时只有定义,只用在运行时才会初始化,这也是为什么const不能用来定义数组的原因,并且const的值也是可以动态修改的. C++中的const是编译时const,故能够用来初始化数组,企图修改const的值是未定义的,如果要修改const的值只能改变const变量的声明方式为 const volatile c=10. 测试用例: const int ci=10; int *j =(int *)&ci; *j=100; printf("%d,%d

修改const变量

看下面的一段代码 1 const int i=0; 2 int * j=(int*)(&i); // 运行正确,j确为i的地址,但 int *j=&i; 编译错误 3 *j=1; //确实改变了i的值 4 printf("%d %d\n",i,*j); //输出0 1 第三行代码执行后,i的值确实已经改变 然而printf的结果确实0 1,这是因为,在C++中对于const变量,在编译期就进行了替换,运行的时候printf中i已经被替换为0了,而*j是从内存中从新取值.

const变量的修改实践

https://bbs.csdn.net/topics/110049293 #include <iostream> using namespace std; int main(){ cout << "const变量实践:" << endl; // 必须加 volatile才会改变 const volatile int a111 = 1; *((int*)&a111) = 22222; cout<<a111<< endl

const关键字和指针

const和指针相结合的四种情况 四种情况分别如下: int cons *p p本身不是常量,p指向的地址的数据为常量 const int *p p本身不是常量,p指向的地址的数据为常量 int * const p p是常量,p指向的地址空间内不是常量 const int * const p p是常量,p指向的地址空间也是常量 总结:当const在*左边是,修饰的是p指向的地址的数据,当const在*右边是,修饰的p 当用const修饰一个变量时,在gcc下,依然可以通过指针修改变量的值 int

数组变量和指针的关系

老师说数组变量可以被看作是const的指针变量,到底是"可以被看作",还是"就是"指针呢? 用程序证据来说明你的观点. (提示:如果对const指针的所有的操作都可以对数组变量做,而且结果一致,就说明数组变量就是指针:如果有某个操作不能做,或者结果不一致,就说明不是指针) #include <stdio.h> int main(){ int a[] = {1,1,2,3,4,5,6,7,8,9,0,}; int *const p = &a[0];

const在修饰指针时的应用

用关键字const修饰一个指针时,根据其位置的不同有不同的含义. 例如: char str1[] = "Point to constant string"; const char *ptr = str1; 表示定义了一个指针ptr,它指向一个常数字符串.因此,运算 *ptr = 'Q'; 是非法的, 因为该字符串为常量. 但指针ptr本身为变量,可以修改.例如 ptr ++; 合法. 而 char str2[] = "A constant pointer"; cha