免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: mickgrady
打印 上一主题 下一主题

二维数组指针,编译器到底为我们处理了多少 [复制链接]

论坛徽章:
0
31 [报告]
发表于 2011-03-16 14:55 |只看该作者
本帖最后由 liexusong 于 2011-03-16 14:59 编辑

看了都头晕, 左值不是可以赋值的吗?

int a[2][2];
*a = xxx;

这样肯定不能编译的, 所以我也觉得*a不是左值, **a才是~
*a只是一个地址, 不能改变一个固定的地址, 只能改变地址指向的内存的值

论坛徽章:
0
32 [报告]
发表于 2011-03-16 16:11 |只看该作者
回复 29# flw2


    int p[2];
*p = 1;
所以*是能作用于数组的,只是p的类型被进行转化成指针了,我第一个帖子里写了
如果你说的是这个,那算你对了, 但是至少p “不是数组而是指针” 这种说法肯定是错的
--------------------------------------------------------------------------------------------------
对!*作用于int*,而不是int[2]。





int a[2][3];
*a当然就不是左值了, 就像
int a[3]; a不是左值一样(a[0]是左值)

你批K&R没关系,但是要是对的,至少K&R两人都不是教授吧
------------------------------------------------------------------
噢,原来你认为*a不是左值的源头在这里。

关于左值,C与C++的观点是不同的,不过,两者不相同的部分与我们所讨论的内容无关。

在标准C里,左值是具有对象类型或非VOID不完整类型的表达式。K&R虽然声称那本书是按照C标准写的,

但其关于左值的定义却不完整,除非他们声明,他们在定义中所声称的对象类型也包括不完整类型(不完整类型描述的是

信息不完整的对象),这也勉强可以。

标准C所取的左值定义,是基于locator的观点而不是赋值运算符左操作数的观点,这意味着它不仅包含可以作为赋值运算符左操作数的表达式,

也包括不能作为左操作数的表达式,例如数组名,数组名在表达式中是具有数组类型(对象类型)的初等表达式,它符合左值的定义,但受语言规则

限制,不能作为左操作数,*a也同样如此。

另:你的治学态度令人赞赏。

论坛徽章:
0
33 [报告]
发表于 2011-03-16 16:26 |只看该作者
回复 29# flw2


    喔,对了,差点漏了,你所举例的那个(********************printf)也是一样作用于指针的

表达式中的函数指示符会隐式转换为该函数类型的指针,就象这里的printf,对于*printf,printf已经隐式转换为函数指针,而不是函数指示符了。

另一方面,*printf的结果依然是一个函数指示符,这导致什么呢?这个函数指示符还会继续隐式转换成函数指针,于是**printf依然可以继续运算,同样道理,

一直进行下去,直到所有*解引用完毕。


但同样的事情无法发生在数组身上,对数组的嵌套逐层剥离的时候,最内层数组的元素类型必定不是数组类型,因此解引用的次数不能超过数组的维度。

论坛徽章:
0
34 [报告]
发表于 2011-03-16 16:28 |只看该作者
看了都头晕, 左值不是可以赋值的吗?

int a[2][2];
*a = xxx;

这样肯定不能编译的, 所以我也觉得*a不 ...
liexusong 发表于 2011-03-16 14:55



    现代C/C++对左值的定义与赋值操作数的左操作数无关。

论坛徽章:
0
35 [报告]
发表于 2011-03-16 16:31 |只看该作者
回复  supermegaboy


怎么个左值法?我原来一直以为int a[2][2]时的*a与int a[2]时的a是一样的东西.
tempname2 发表于 2011-03-16 13:11



    int a[2][2]的*a与int a[2]中的a是同样的类型int[2]。

论坛徽章:
0
36 [报告]
发表于 2011-03-16 19:14 |只看该作者
回复  flw2


    int p[2];
*p = 1;
所以*是能作用于数组的,只是p的类型被进行转化成指针了,我第一 ...
supermegaboy 发表于 2011-03-16 16:11


C参考手册和C99上说,数组是左值。但是C参考手册后面又接着说:不能做为左值的表达式包括:数组名....

C参考手册自相矛盾了。不知道各位如何看待这个问题。
现在我倾向把数组作为不可修改的左值处理。

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
37 [报告]
发表于 2011-03-16 19:25 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
38 [报告]
发表于 2011-03-16 19:32 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
39 [报告]
发表于 2011-03-16 19:54 |只看该作者
回复 1# mickgrady


    我觉得您可以看看《狂人C》的指针那章
   http://blog168.chinaunix.net/space.php?uid=23387202&do=blog&id=35525

论坛徽章:
0
40 [报告]
发表于 2011-03-16 21:31 |只看该作者
这是标准写的, 确实大家对左值理解都不一样,所以讨论也没什么对错可言了

An lvalue is an expression with an object type or an incomplete type other than void;
  if an lvalue does not designate an object when it is evaluated, the behavior is undefined.
  When an object is said to have a particular type, the type is specified by the lvalue used to   designate the object. A modifiable lvalue is an lvalue that does not have array type, does   not have an incomplete type, does not have a const-qualified type, and if it is a structure  or union, does not have any member (including, recursively, any member or element of  all contained aggregates or unions) with a const-qualified type.


Except when it is the operand of the sizeof operator, the unary & operator, the ++
  operator, the -- operator, or the left operand of the . operator or an assignment operator,
  an lvalue that does not have array type is converted to the value stored in the designated
   The cast and assignment operators are still required to perform their specified conversions as
       described in 6.3.1.4 and 6.3.1.5.



The name ‘‘lvalue’’ comes originally ---------------------------

from the assignment expression E1 = E2, in which the left
       operand E1 is required to be a (modifiable) lvalue. It is perhaps better considered as representing an
       object ‘‘locator value’’. What is sometimes called ‘‘rvalue’’ is in this International Standard described
       as the ‘‘value of an expression’’.
       An obvious example of an lvalue is an identifier of an object. As a further example, if E is a unary
       expression that is a pointer to an object, *E is an lvalue that designates the object to which E points.
  
  object (and is no longer an lvalue). If the lvalue has qualified type, the value has the
  unqualified version of the type of the lvalue; otherwise, the value has the type of the
  lvalue. If the lvalue has an incomplete type and does not have array type, the behavior is
  undefined.


Except when it is the operand of the sizeof operator or the unary & operator, or is a
  string literal used to initialize an array, an expression that has type ‘‘array of type’’ is
  converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
  the array object and is ___not ____ an lvalue.

这段话说 T t[N], t的类型大多数时候是 T*, 而且它不是左值, 同样int a[2][3]; *a hash type of "array of int" , so converted to int *, and is not an lvalue
K&R也是这个意思, 这也是我上面帖子的来源参考
不管怎么理解左值,标准这一段(上面几段我不知所言)确实说int a[2][3]; *a不是左值

C语言参考手册基本就是抄标准的吧,我这里也有,没怎么看过,很像
KBTiller 写的不错,也和标准也很像
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP