免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: _HellAngel_

[C] 关于指针的地址运算符&(新手请教) [复制链接]

论坛徽章:
11
摩羯座
日期:2013-09-16 11:10:272015亚冠之阿尔萨德
日期:2015-06-12 22:53:29午马
日期:2014-04-15 11:08:53亥猪
日期:2014-03-02 23:46:35申猴
日期:2013-12-06 22:07:00亥猪
日期:2013-11-28 12:03:13双鱼座
日期:2013-11-21 14:43:56亥猪
日期:2013-10-23 10:55:49处女座
日期:2013-10-17 18:15:43午马
日期:2013-09-27 17:40:4215-16赛季CBA联赛之青岛
日期:2016-06-22 00:45:55
发表于 2012-12-15 18:21 |显示全部楼层
pmerofc 发表于 2012-12-15 16:24
回复 19# Ager

    订正岂敢。写得相当好。
   提点小建议
   (6)中的代码,加上变量的声明也许更好


感谢pm大虾支持:)

已按大虾你的建议,修正相关部分内容。

论坛徽章:
11
摩羯座
日期:2013-09-16 11:10:272015亚冠之阿尔萨德
日期:2015-06-12 22:53:29午马
日期:2014-04-15 11:08:53亥猪
日期:2014-03-02 23:46:35申猴
日期:2013-12-06 22:07:00亥猪
日期:2013-11-28 12:03:13双鱼座
日期:2013-11-21 14:43:56亥猪
日期:2013-10-23 10:55:49处女座
日期:2013-10-17 18:15:43午马
日期:2013-09-27 17:40:4215-16赛季CBA联赛之青岛
日期:2016-06-22 00:45:55
发表于 2012-12-15 18:24 |显示全部楼层
蔡万钊 发表于 2012-12-15 16:01
相当好啊!!!!! 如果 THQ 能有这份心,还怕那么多人学不会么?!

folklore 发表于 2012-12-15 17:50
阿哥V5,8741

captivated 发表于 2012-12-15 17:54
mark顶ager.


感谢蔡大虾、folklore大虾、captivated大虾支持,呵呵 :)

论坛徽章:
3
寅虎
日期:2013-11-27 07:53:29申猴
日期:2014-09-12 09:24:152015年迎新春徽章
日期:2015-03-04 09:48:31
发表于 2012-12-15 18:42 |显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
11
摩羯座
日期:2013-09-16 11:10:272015亚冠之阿尔萨德
日期:2015-06-12 22:53:29午马
日期:2014-04-15 11:08:53亥猪
日期:2014-03-02 23:46:35申猴
日期:2013-12-06 22:07:00亥猪
日期:2013-11-28 12:03:13双鱼座
日期:2013-11-21 14:43:56亥猪
日期:2013-10-23 10:55:49处女座
日期:2013-10-17 18:15:43午马
日期:2013-09-27 17:40:4215-16赛季CBA联赛之青岛
日期:2016-06-22 00:45:55
发表于 2012-12-15 19:56 |显示全部楼层
本帖最后由 Ager 于 2012-12-16 04:25 编辑
书中说到,上面第二个语句,也就是:
   *ip += 1;
它等同于,
   ++*ip;

   (*ip)++;
最后那个语句中的圆括号是必须的,否则,该表达式将对ip进行加一运算而不是对ip指向的对象进行加一运算。
这是因为,类似于*和++这样的一元运算符遵循从右至左的结合顺序。
这边我注意到,是结合顺序。写到这里,我又有了一个疑问,就是结合顺序和运算顺序,这是数学基础的概念。


这是初学者特别容易犯胡涂的地方。

之所以
  1. (*ip)++;
复制代码
要用上小括号才能等同于本初的语句,那是因为作为后缀运算符的“++”之优先级比间接访问运算符“*”的,要高,而不是因为“结合性”的问题。

而所谓“结合性”,是指:若一个操作数的左右两边,同时出现两个运算符,而两下的优先级又相同,为了让该操作数解除困惑,该操作数将依照同属一个优先级的操作符们所被规定的结合性,选择跟两个操作符中的一个,先行组合。具体地说,若一个操作符具有“从左到右”的结合性(或索性简称“左结合性”),则“发生困惑的”操作数与它左边的操作符,先行组合,成为一个小群组。

这好比:我家的Jiafei(母猫)被左边的Dahong和右边的Renzui这两只公猫夹在中间,准确地说,Jiafei是被夹在了两个“交配”的运算符之间。Jiafei一次只能跟一只公猫交配,那么,她应该选择跟哪只公猫交配呢?(因为各种交配运算同属于一个优先级。)根据各种交配运算所同属于的一个优先级上的结合性,比如是“左结合性”,Jiafei应该单单跟左边的Dahong先行交配,诞下一只新的小母猫。然后这只小母猫再与右边的Renzui交配。不过,如果Jiafei和Dahong这次所诞下的是一只小公猫的话,那么,对于右边有Renzui的交配运算符来说,就是:遭遇到了非法操作数。。。

—— 这里,蕴涵了一个事实:同属一个优先级的操作符们,具有相同的结合性,否则,被夹在操作符中间的操作数,仍将“左右为难”。

而,另外的一条语句
  1. ++*ip;
复制代码
不存在“优先级”问题,所以也不存在“结合性”问题。因为,无论如何,操作数ip都是仅仅被间接访问运算符“*”所作用。

同理的例子,还有:
  1. *++ip;
复制代码
不过,这条语句,除了让ip的“值被刷增了1”以外(即ip所对应的内存对象,被更改为原来的对象的后面的一个),没有什么其他作用。这条语句等同于:
  1. ++ip;
复制代码
但下面这样的语句,就是错误的:
  1. ++++ip;
复制代码
  1. ++(++ip);
复制代码
以及
  1. ip++++;
复制代码
  1. (ip++)++;
复制代码
因为:不论是作为前缀运算符的“++”还是作为后缀运算符的“++”,它们合法的操作数,必须是一个可以被刷写的左值(也就是说,该左值表达式所handle的内存对象可以被刷写)。

含有前缀的运算符“++”和后缀的运算符“++”的表达式,统称“增值表达式”。这样的表达式具有一个返回结果:前缀增值表达式的返回结果是操作数被“增1”的值,后缀增值表达式的返回结果是操作数的值(不“增1”,即在作为操作数的左值所handle的内存对象上的数据值被“增1”这个副作用发生之前,该内存对象上的数据值)。

而这个返回结果,不再是左值,所以,它们无法成为靠外边(即远离操作数ip)的那个“++”的合法操作数。

这种错误,跟
  1. ++123;
复制代码
  1. 123++;
复制代码
的错误,是一个道理。

最后,补充说一下:

前面说了,作为后缀运算符的“++”之优先级比间接访问运算符“*”的要高。而另一方面,作为前缀运算符的“++”之优先级与间接访问运算符“*”的,是相同的。

不过,这基本上不会发生什么问题,因为作为前缀运算符的“++”与间接访问运算符“*”,都总是在它们的操作数的左侧,那么两者同时出现在操作数的左侧,势必一前一后,即仅有一个操作符紧贴着操作数。换句话说,你永远写不出这样的语句:

  1. ++
  2.     ip   ;
  3. *
复制代码
如果这样的语句是合法的话,那么,就需要一个“上下结合性”的规则了,呵呵,开个玩笑 ……

以上,仅供参考,呵呵 —— :)



论坛徽章:
0
发表于 2012-12-15 21:48 |显示全部楼层
回复 21# pmerofc

register可以算memory/内存(反正可以肯定不算外存),也可以不算——仅当不需要严格地分辨存储体系的成分,考虑附加限制“内存一定可以寻址”时(例如“memory address”翻译成“内存地址”)。可惜不严格的场合太多,似乎变成约定俗成了,但这并不表示所有场合都适用。这里需要区分在和不在寄存器中的存储,用memory这种统称就有些不妥了。在C标准(尽管只是EXAMPLE)出现这样笼统的说法倒是让我有些意外。
此外,“内存”的真正含义应该是指无法脱机的存储,memory自然包括硬盘之类的secondary memory,无条件翻译成“内存”都是有些问题的。不过C不需要在这里区分memory到底是不是联机存储,所以不管register的时候用memory倒是没问题。不过翻译嘛……如果不说“主存”好像还真只能称为“内存”了(“存储器”这种更笼统的称谓只会导致更乱;“存储”(存储空间)在C里面一般指storage这种抽象而不是被抽象的体系对应的成分,尽管在C以外storage和memory有时候可以通用)。

论坛徽章:
0
发表于 2012-12-15 21:55 |显示全部楼层
回复 35# 幻の上帝
其实这里的关键是,或许memory一词的用法太过约定俗成,ISO C没有像ISO C++这样表示如何对存储进行抽象的明确的memory model说明这个memory指的是什么:ISO C++ 1.7 The memory available to a C++ program consists of one or more sequences of contiguous bytes. Every byte has a unique address.——理直气壮地无视不可寻址的存储,不管register在实现中对应什么,甚至C++11中顺理成章地把register关键字都给deprecated掉了。

论坛徽章:
0
发表于 2012-12-15 21:59 |显示全部楼层
回复 36# 幻の上帝

顺便,ISO C11在概念上还有新的问题:
WG14/N1570
3.14
1 memory location
either an object of scalar type, or a maximal sequence of adjacent bit-fields all having nonzero width
这话放在C++11毫无问题,但放在这里就有些问题了。寄存器变量算不算呢?(注意这可是标准正文。)

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
发表于 2012-12-15 22:43 |显示全部楼层
@幻の上帝
Register是可以寻址的(每一个寄存器都有一个编号,如果只有一个寄存器,好吧,它有一个显然的用不了提示的地址0),你说的寄存器也是内存也没有问题。

在硬件上,寄存器和内存是用相同技术实现的。
它们不同点在于,内存只能通过外部Bus和 内存控制器存取,外部时钟比较慢一点。
而寄存器是集成在CPU片内,直接通过内部连线和计算单元连接。

这里强调CPU是因为,外部设备的端口(有时也被Map为Memory)也没有异义是也叫寄存器。

论坛徽章:
0
发表于 2012-12-15 22:55 |显示全部楼层
folklore 发表于 2012-12-15 22:43
@幻の上帝
Register是可以寻址的(每一个寄存器都有一个编号,如果只有一个寄存器,好吧,它有一个显然的用 ...

好吧,我要表达的更确切地意思是“(像主存那样地)按字节寻址”。
orz...其实我回完3帖之后重读一遍就发现一开始说得还是不够清楚了……真的。叵耐我这里CMCC卡成翔了,死活刷新不出CU的页面(之前也没刷新出发帖按钮啥的,好在有Ctrl+Enter)。买回夜宵发现卡了大半个小时居然还没动静,又刷了5分钟,总算出来了……


论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
发表于 2012-12-15 22:56 |显示全部楼层
@_HellAngel_
Register变量不能寻址,是因为C语言没办法直接操作寄存器。

什么,崁入汇编?这个,这个。。。































崁入机器代码也算么?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP