关于指针赋值和const的疑惑

Z. X. Y. 2018-07-30 03:05:29
以下摘自《C Primer Plus》第10章:数组和指针,第6节:保护数组中的数据。第301页。人民邮电出版社 2016年4月第一版

关于指针赋值和const需要注意一些规则。首先,把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的:
double rates[5]={88.99, 100.12, 59.45, 183.11, 340.5};
const double locked[4]={0.08, 0.075, 0.0725, 0.07};
const double*pc=rates; //有效;
pc=locked; //有效;
pc=&rates[3]; //有效;

疑问:“把const数据或非const数据的地址初始化为指向const的指针”这句话什么意思?
书中一共写了3个例子:
const double*pc=rates; //有效;
pc=locked; //有效;
pc=&rates[3]; //有效;
我觉得第一个例子应该是代表“非const数据的地址初始化为指向const的指针”这句话的。
可是第一个例子不是初始化指针pc么?这跟“非const数据的地址初始化为指向const的指针”矛盾吗?我理解这句话的意思是,把非const的数据初始化,接着把这个非const的数据变成一个指针。
我是不是理解错了?
...全文
221 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2018-08-01
  • 打赏
  • 举报
回复
总之纠结const这种鸡肋,我觉得是浪费青春。
Z. X. Y. 2018-07-30
  • 打赏
  • 举报
回复
引用 9 楼 qq_41985711 的回复:
[quote=引用 8 楼 _sseakom的回复:]不要绕这个句子了。你要将它转换为自己的语言。
int a[10] = {0};

//前半句,用非const数据初始化为指向const类型的指针。
int const *p = a;

//这个指针可以被赋值,也就是改p的指向。
p = &a; //注意这两个p的指向是不一样的,前一个指向的是数组的首元素,而后一个被赋值的p是指向整个数组的。

//简单来说就是指针你可以随便玩,而指针指向的那片内存里的东西你不能动。动了就是非法。

手机打的,排版不好,见谅



突然想到一个好的解释
int a[10] = {0};
int const *p = a;
那么这个p依然可以做表达式的左值
而 *p就不可以做表达式的左值[/quote]
谢谢!你重新举例后,我算是感觉到了这句话的主旨,是我太纠结文字了。
李财日记 2018-07-30
  • 打赏
  • 举报
回复
引用 8 楼 _sseakom的回复:
不要绕这个句子了。你要将它转换为自己的语言。 int a[10] = {0}; //前半句,用非const数据初始化为指向const类型的指针。 int const *p = a; //这个指针可以被赋值,也就是改p的指向。 p = &a; //注意这两个p的指向是不一样的,前一个指向的是数组的首元素,而后一个被赋值的p是指向整个数组的。 //简单来说就是指针你可以随便玩,而指针指向的那片内存里的东西你不能动。动了就是非法。 手机打的,排版不好,见谅
突然想到一个好的解释 int a[10] = {0}; int const *p = a; 那么这个p依然可以做表达式的左值 而 *p就不可以做表达式的左值
李财日记 2018-07-30
  • 打赏
  • 举报
回复
不要绕这个句子了。你要将它转换为自己的语言。 int a[10] = {0}; //前半句,用非const数据初始化为指向const类型的指针。 int const *p = a; //这个指针可以被赋值,也就是改p的指向。 p = &a; //注意这两个p的指向是不一样的,前一个指向的是数组的首元素,而后一个被赋值的p是指向整个数组的。 //简单来说就是指针你可以随便玩,而指针指向的那片内存里的东西你不能动。动了就是非法。 手机打的,排版不好,见谅
Z. X. Y. 2018-07-30
  • 打赏
  • 举报
回复
引用 3 楼 zhao4zhong1 的回复:
[quote=引用 2 楼 weixin_42834292 的回复:]
[quote=引用 1 楼 zhao4zhong1 的回复:]
不要纠结各种常量了,这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢!

赵老师,能不能帮我解个惑呀,这句话好烦人啊,把我整懵圈了[/quote]
const只能在编译期防止常量错用,在运行期就无能为力了。[/quote]
额...赵老师,我刚开始学C语言,这句话我只能看懂前一句,后一句就有点晕了
我现在对“把const数据或非const数据的地址初始化为指向const的指针”有一点新的理解。我啰嗦一下。
主语:const数据或非const数据的地址
谓语:初始化
宾语:指向const的指针
因为个人对这句话的理解还是比较倾向const double*pc=rates(因为只有他进行了指针pc的初始化)。我就以主谓宾来陈述自己的思路
主语:非const数据的地址。指针pc
谓语:初始化 ,就是const double*pc=rates;因为他在声明的过程中,进行了赋值的操作(我把声明过程中的赋值理解为初始化和赋值的区别)
宾语:指向const的指针。const double *pc。
说实话,这个主语我就说服不了我自己,我只是强行去解读。因为在此之前pc并没告知是const还是非const。
不知道我这样理解对不对。

刚开始学C,很多地方学的还不扎实,还望赵老师能指点迷津,谢谢了!
Z. X. Y. 2018-07-30
  • 打赏
  • 举报
回复
引用 4 楼 qq_41985711 的回复:
首先 const 修饰是变量,用 const 只能保证程序不能去修改它,即在程序中他是只读的。但外部条件依然可以导致你的这片内存发生变化。
要修饰指针有三种写法
第一种:
int a = 0;
int * const p = &a; 这样p就在程序中一直指向固定的内存,但是这片内存里面存的数据是可以变的:当然正常人基本不会这样写代码。
第二种:
int a[10] = {0};
const int *p= a; 或者int const *p = a; 这样p指向的这片内存在程序中就不能通过p去改变,而指针的指向是可以变的。只是无法通过
该指针去修改a里面的元素
例如:*(p + 1) = 2; 这是非法的,当然如果你再定义一个指针 int *q = a; 这样你依然可以通过指针 q 来修改 a 里面的元素。
即 *(q + 1) = 2; 是合法的
第三种:
int a[10] = {0};
const int * const p = a; 这样 p 就指向固定内存,也不可以通过p来对p指向内存的数据进行操作。我认为这种代码存在的意义不大

当const不修饰指针的时候,就代表改变量只读,就是通过程序无法改变你这个变量,并且只有一次初始化的机会。
例如:const int a = 5; //那么a就一直是5,不能通过程序取改变它
a = 10; //非法

注意:虽然程序不能改变const变量,但外部条件依旧可以改变const变量。比如在程序运行时,硬件的变动可能会触碰
到你那片只读内存,而你的程序是无法阻止的。

谢谢兄弟,辛苦了!仔细拜读了你的回复,然后自己又去百度了一下。
总结起来,就是const在*的左边,那么值就不能改变,如果在右边就指向不能改变。
即,const在*的左边,就是指向const的指针;const在*的右边,就是const指针。
不知道我理解的对不对。
另外,你说“把const数据或非const数据的地址初始化为指向const的指针”这句话的解释其实是第二个例子“pc=locked;”
这个跟我理解的不太一样:
1.const double*pc=rates; pc在这一行已经完成了初始化。
2.pc=locked,因为已经完成了初始化,所以这一行,我的理解是进行再赋值。因为const在*的左边,把locked的首地址赋给pc。
我现在对“把const数据或非const数据的地址初始化为指向const的指针”也有一点新的理解。我啰嗦一下。
主语:const数据或非const数据的地址
谓语:初始化
宾语:指向const的指针
因为个人对这句话的理解还是比较倾向const double*pc=rates(因为只有他进行了指针pc的初始化)。我就以主谓宾来陈述自己的思路
主语:非const数据的地址。指针pc
谓语:初始化 ,就是const double*pc=rates;因为他在声明的过程中,进行了赋值的操作(我把声明过程中的赋值理解为初始化和赋值的区别)
宾语:指向const的指针。const double *pc。
说实话,这个主语我就说服不了我自己,我只是强行去解读。因为在此之前pc并没告知是const还是非const。
不知道我这样理解对不对。

刚开始学C,很多地方学的还不扎实,还望兄弟能指点迷津,谢谢了!

李财日记 2018-07-30
  • 打赏
  • 举报
回复
显然你的就是第二种情况
李财日记 2018-07-30
  • 打赏
  • 举报
回复
首先 const 修饰是变量,用 const 只能保证程序不能去修改它,即在程序中他是只读的。但外部条件依然可以导致你的这片内存发生变化。
要修饰指针有三种写法
第一种:
int a = 0;
int * const p = &a; 这样p就在程序中一直指向固定的内存,但是这片内存里面存的数据是可以变的:当然正常人基本不会这样写代码。
第二种:
int a[10] = {0};
const int *p= a; 或者int const *p = a; 这样p指向的这片内存在程序中就不能通过p去改变,而指针的指向是可以变的。只是无法通过
该指针去修改a里面的元素
例如:*(p + 1) = 2; 这是非法的,当然如果你再定义一个指针 int *q = a; 这样你依然可以通过指针 q 来修改 a 里面的元素。
即 *(q + 1) = 2; 是合法的
第三种:
int a[10] = {0};
const int * const p = a; 这样 p 就指向固定内存,也不可以通过p来对p指向内存的数据进行操作。我认为这种代码存在的意义不大

当const不修饰指针的时候,就代表改变量只读,就是通过程序无法改变你这个变量,并且只有一次初始化的机会。
例如:const int a = 5; //那么a就一直是5,不能通过程序取改变它
a = 10; //非法

注意:虽然程序不能改变const变量,但外部条件依旧可以改变const变量。比如在程序运行时,硬件的变动可能会触碰
到你那片只读内存,而你的程序是无法阻止的。
赵4老师 2018-07-30
  • 打赏
  • 举报
回复
引用 2 楼 weixin_42834292 的回复:
[quote=引用 1 楼 zhao4zhong1 的回复:]
不要纠结各种常量了,这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢!

赵老师,能不能帮我解个惑呀,这句话好烦人啊,把我整懵圈了[/quote]
const只能在编译期防止常量错用,在运行期就无能为力了。
Z. X. Y. 2018-07-30
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
不要纠结各种常量了,这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢!

赵老师,能不能帮我解个惑呀,这句话好烦人啊,把我整懵圈了
赵4老师 2018-07-30
  • 打赏
  • 举报
回复
不要纠结各种常量了,这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢!

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧