免费注册 查看新帖 |

Chinaunix

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

[C] [原创]对于C语言中指针和数组的认识和看法,欢迎讨论 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2007-07-11 22:22 |只看该作者
>> “左值语义”和“右值语义”是如何定义和区分的?

如果操作符(包括函数调用)的操作数是一个表达式(而不是一个名字、类型或其它),则这样的操作符规定了其操作数的语义环境是左值还是右值。详细可参见各个操作符的说明。

在《C++ Primer》一书中提供了一张关于 C++ 的“操作符优先级(Operator Precedence)”表,明确指出了各个操作符的操作数应该是左值(lvalue)还是右值 (expr、pointer等)(对于表达式操作数而言),或其它(对于非表达式操作数而言)。去掉表中 C++ 专有的操作符之后,也同样适用于 C。

论坛徽章:
0
12 [报告]
发表于 2007-07-11 23:14 |只看该作者
《C++ Primer》那个表我看了一下,不过有些疑问

>>在左值语义下是数组类型

>>例如 &a 以及 sizeof(a) 中的 a 都处于左值语义下,所以 a 仍然是数组类型。

1. &a+1该如何解释呢?

2. 表中sizeof是不需要lvalue的,是expr

3. 操作符优先级(Operator Precedence)”表中expr并不是专指rvalue,他包括lvaule和rvalue
之所以有的要强调lvaule,那是因为该操作符只能操作与lvaule的
而应用于expr的操作符则lvalue和rvalue皆可

4. a是不容改变的,它应该不能出现在所谓的 "左值语义”中

所以,根据所谓的"左值语义”和“右值语义”是很不好区分和解释的


原帖由 whyglinux 于 2007-7-11 22:22 发表
如果操作符(包括函数调用)的操作数是一个表达式(而不是一个名字、类型或其它),则这样的操作符规定了其操作数的语义环境是左值还是右值。详细可参见各个操作符的说明。

在《C++ Primer》一书中提供了一张关于 C++ 的“操作符优先级(Operator Precedence)”表,明确指出了各个操作符的操作数应该是左值(lvalue)还是右值(expr、pointer等)(对于表达式操作数而言),或其它(对于非表达式操作数而言)。去掉表中 C++ 专有的操作符之后,也同样适用于 C。

[ 本帖最后由 ypxing 于 2007-7-11 23:18 编辑 ]

论坛徽章:
0
13 [报告]
发表于 2007-07-12 14:08 |只看该作者
  楼主的精神非常值得肯定和表扬,要是做技术的都像你这么认真就好了,是我学习的榜样。
  对于楼主提出的观点我比较赞同,指针其实就是一种普通变量而已,函数传地址实际就是传值等等,从本质上来讲确实如此,但是不好这么去下定义,因为从不同的层次和角度出发去看,是会不一样的,这样可能会误倒不少新手。从底层向上看问题,和从应用上层往下看问题,得到的观点极有可能不一致。
  另外,极力反对讨论c的时候把c++牵扯进来,在我看来,c和c++压根就是完全不同的两种语言,没有什么可比性,c++完全就不是什么c的超集,它们在对一些基本问题上是完全不一样的。例如,左值和右值的概念就完全不一样,不能把c++中的东西拿来套c,在c中,左值和右值的概念其实是非常简单的,远远没有c++中复杂。

论坛徽章:
0
14 [报告]
发表于 2007-07-12 15:16 |只看该作者
一个数字常量也可以转成指针来用:
比如你提前知道一个int变量的地址是0xffaa,想对它assign,就这么做
*((int *)0xffaa)  =  100;        // assign 100 to this value

如果你提前知道了一个函数的地址,设为0xffaa, 那么你可以这么调用它:
typedef int (*t_pfun) (int , int)  // 假设那个函数是这样的

result = ((t_pfun)0xffaa) (100, 200);

这些方法请小心使用,如果使用不当很容易把程序搞崩

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
15 [报告]
发表于 2007-07-12 16:06 |只看该作者
原帖由 xxandxx 于 2007-7-12 15:16 发表
一个数字常量也可以转成指针来用:
比如你提前知道一个int变量的地址是0xffaa,想对它assign,就这么做
*((int *)0xffaa)  =  100;        // assign 100 to this value

如果你提前知道了一个函数的地址, ...


这种写法是披着羊皮(C)的狼(汇编)

论坛徽章:
0
16 [报告]
发表于 2007-07-12 19:08 |只看该作者
是这样的,
例如:++i在C++中是一个lvalue,在C中++i是一个rvalue
http://bbs.chinaunix.net/viewthread.php?tid=941407

原帖由 Sorehead 于 2007-7-12 14:08 发表 极力反对讨论c的时候把c++牵扯进来,在我看来,c和c++压根就是完全不同的两种语言,没有什么可比性,c++完全就不是什么c的超集,它们在对一些基本问题上是完全不一样的。例如,左值和右值的概念就完全不一样,不能把c++中的东西拿来套c

论坛徽章:
0
17 [报告]
发表于 2007-07-12 19:48 |只看该作者
int a[5]; 中的a在C中就是一个指向第一个元素整数的常数指针. a + 1 == &a[5] 只是编译后来的扩展. 知道了就可以了. 按前面理解许多时候更好.

看这个-------------

  1. int a[0];

  2. int func(int a[8])
  3. {
  4.    printf("size %p\n", sizeof(a));  //??
  5. }

  6. main()
  7. {
  8. int b[8];
  9.    func(b);
  10.    printf("%p %p\n", a, a+1);  //??
  11. }
复制代码

论坛徽章:
0
18 [报告]
发表于 2007-07-12 20:17 |只看该作者
main函数中的a和a+1是没有问题的,跟我的理解相符

其实,func的原型相当于int func(int *a);

  1. int func(int a[8])
  2. {
  3.   printf("size %d, %d, %p, %p\n", sizeof(a), sizeof(*a), a, a+1);  //执行这一句就ok了
  4. }
复制代码

int func2(int a[3][5]);相当于int func2(int (*a)[5]);

int func3(int a[3][5][8]);相当于int func3(int (*a)[5][8]);

以此类推...


原帖由 思一克 于 2007-7-12 19:48 发表 int a[0];

  1. int func(int a[8])
  2. {
  3.    printf("size %p\n", sizeof(a));  //??
  4. }

  5. main()
  6. {
  7. int b[8];
  8.    func(b);
  9.    printf("%p %p\n", a, a+1);  //??
  10. }
复制代码

[ 本帖最后由 ypxing 于 2007-7-12 20:26 编辑 ]

论坛徽章:
0
19 [报告]
发表于 2007-07-12 20:20 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
20 [报告]
发表于 2007-07-12 22:00 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP