社区
C语言
帖子详情
突然对指针的感悟,不知道正确与否。
program2050
2012-02-23 12:49:55
感悟1:
指针中保存的内容是地址
感悟2:
int *a = NULL, b = 10;
a = &b;
a 等价于 *(&a),等价于&(*a)
*a 同样等价于 *(*(&a))
...全文
2157
91
打赏
收藏
突然对指针的感悟,不知道正确与否。
感悟1: 指针中保存的内容是地址 感悟2: int *a = NULL, b = 10; a = &b; a 等价于 *(&a),等价于&(*a) *a 同样等价于 *(*(&a))
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
91 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
潇湘夜雨
2012-02-29
打赏
举报
回复
咬概念,么得啥子意思
Ever_lover
2012-02-29
打赏
举报
回复
*是指向什么什么的意思,&是取呢个地址的内容,有点不同
complayer
2012-02-29
打赏
举报
回复
lvalue必须是一块内存区域,等同于变量的表达式,具体形式可能多种多样。
比如: a, b[3], c.value,*d->next等等。
根据这个表达式必须能够确定某块内存区域。
这玩意好像还真得用汇编才能说清楚,它是[100]和100的区别,[100]告诉CPU去100这个地址去取操作数,100则是把100当作操作数。如果去看具体的指令,则是寻址方式的差异,间接寻址和立即寻址。
比如:
MOV [100], 33 ; 把33存入地址为100的位置
ADD [100], 100 ; 从地址100的位置取第一个操作数33,加上立即数100,结果133存入[100]。
; 最后结果是内存地址为100的位置值变为133。
如果我们把[100]命名为int a,那么就等同于下面的语句:
a = 33;
a += 100;
complayer
2012-02-29
打赏
举报
回复
lvalue必须是一块内存区域,等同于变量的表达式,具体形式可能多种多样。
比如: a, b[3], c.value,*d->next等等。
根据这个表达式必须能够确定某块内存区域。
这玩意好像还真得用汇编才能说清楚,它是[100]和100的区别,[100]告诉CPU去100这个地址去取操作数,100则是把100当作操作数。如果去看具体的指令,则是寻址方式的差异,间接寻址和立即寻址。
比如:
MOV [100], 33 ; 把33存入地址为100的位置
ADD [100], 100 ; 从地址100的位置取第一个操作数33,加上立即数100,结果133存入[100]。
; 最后结果是内存地址为100的位置值变为133。
如果我们把[100]命名为int a,那么就等同于下面的语句:
a = 33;
a += 100;
complayer
2012-02-29
打赏
举报
回复
我发现表述上还是有问题。
变量应该是一块内存区域的别名(连续或不连续)。
我们通常把一块内存区域的首地址作为它的的地址,也就是&操作符取到的值,指定时刻它是一个常数,一个标量值。
秦剑
2012-02-29
打赏
举报
回复
指针是一个内存单元,是一个变量
complayer
2012-02-28
打赏
举报
回复
通俗地讲左值(lvalue)是能够放在赋值操作符左侧的表达式,右值(rvalue)是只能放在赋值操作符右侧的表达式。赋值是往特定的内存地址写入内容,所以lvalue必须有确定的内存地址,否则没法写入,或者写入后很快被覆盖,比如只保存在寄存器上的值,临时变量(函数的返回值)等。
1+2这个表达式的结果就是一个rvalue,有值但没有确定的地址。
int a; 变量a就有确定的地址,可以读取内容也可以写入内容,比如a=3。a是一个lvalue。
反之a+3就是一个rvalue,只是一个临时的值,不立即保存的话就没法访问了。
lvalue的值该语句结束后还可以访问。
rvalue的值如果在本语句不保存的话,就不能访问了。
int *p, a[10];
p = a;
p; // lvalue
*p; // lvalue
p+1; // rvalue,是指针值
*(p+1); // lvalue
*p+1; // rvalue
a; // lvalue
&a; // rvalue,是指针值
a+1; // lvalue
*a; // rvalue
(int *)100; // rvalue,是指针值
容易混淆的是指针和指针值,正如变量是内存地址的别名一样,指针(全称指针变量)也是内存地址的别名,而指针值则是该内存地址中保存的值。上面的例子中p是一个指针变量,p的值是a的地址,32位系统中是一个32位的无符号整数,可以转换为整数打印出来。int a = 3; a是变量,某个内存地址的别名,a的值是3。p=NULL; p是指针,某个内存地址的别名,p的值是NULL(0)。
需要好好体会,呵呵。理解lvalue和rvalue如果有一定的汇编基础会容易点。上面很多的回帖说的都是关于指针这方面的特性。单个指针很好确定,如果是比较复杂的指针表达式到底是lvalue还是rvalue容易犯晕。
我发现指针的复杂性主要是*操作符引入的,它能将一个rvalue转变为lvalue。
*((int *)1000) = 999;
等价于:
int *p = (int *)1000;
*p = 999;
(int *)1000 = 999; // 是错误的。
怎么理解呢?1000是一个整型常数(rvalue),(int *)将其强制类型转换后还是常数(rvalue),只是类型发生了变化变成了整型指针值,原来是int,现在变成了int *。
&操作符返回的是一个指针值(rvalue),而不是指针,只是一个值而已。清楚这一点就容易了。
一个指针值(类似整数值)可以使用运算符有+, -, *,+或-的时候与指针值的数据类型有关,比如整型指针值+1,指针值增加的是sizeof(int),32位系统下为4。char指针值+1,指针增加的是sizeof(char)=1。
lvalue可以当作rvalue用,反之不行。因为我们可以把lvalue的值(rvalue)取出来参与运算。
muyi66
2012-02-28
打赏
举报
回复
那你这么理解:左值就是能放到赋值符('=')左边的值,左值表示存放数据的位置。
zyzhaojun
2012-02-28
打赏
举报
回复
[Quote=引用 76 楼 complayer 的回复:]
看了一下上面的系列回帖,写得好乱。主要是关于&操作符的返回值到底是lvalue还是rvalue,非常乱。
int a, b, *p1, **p2;
&a = &b; // 错误,虽然类型相同都是int *,但是因为&a是rvalue。
p1 = &a;
p2 = &p1;
&p1 = p2; //错误,虽然类型……
[/Quote]
你思考得很好!但最好用些贴近老百姓的通俗话来讲一下什么是左值,什么是右值?
莫讲一些“左值是能够被赋值的值,右值是能够给左值赋值的值”之类的循环论证的话,最好莫搬课本和术语,好让观众清楚明白。
低头思蚊香
2012-02-28
打赏
举报
回复
这贴也能上首页。。没什么意思啊
帅牛
2012-02-28
打赏
举报
回复
学习了,学习了。。。谢啦!~
complayer
2012-02-28
打赏
举报
回复
呵呵,没关系,俺不在乎分数,在乎结果。
通过回复,也让我梳理了一下自己的思路,加深了认识。
program2050
2012-02-28
打赏
举报
回复
[Quote=引用 71 楼 complayer 的回复:]
heronism说a等价于&(*a),这个不太理解。*a放的是b的值,a放的是b的地址,&(*a)一定要放b的地址吗,为什么不能是其他和b的值相等的变量的地址。
*a表达式是一个L-Value,是一个内存地址,所以可以用&运算符作用于它。至于为什么这样,因为*运算符就是这样定义的,呵呵。
&a返回的是一个R-Value,a == &(*a),但是……
[/Quote]
complayer 回答得好详细。可惜结贴给分得太早了。。。。
complayer
2012-02-28
打赏
举报
回复
rvalue通过*操作符能转换为lvalue,所以一定要关注该操作符。
&(*p)是rvalue;
*(&p)是lvalue;
就是这个道理。
单个变量是lvalue。
struct tagNode
{
int value;
struct tagNode *next;
} *root;
root = new tagNode;
root->next = new tagNode;
新创建的这两个元素都没有名字,只能通过指针来引用。
delete root->next;
delete root;
new操作符返回的也是一个指针值,而不是指针。
(*new tagNode).value =10;
这里出现内存泄漏了。
complayer
2012-02-28
打赏
举报
回复
表达式计算结果通常都是rvalue,是临时结果,必须保存起来才行。我们通常会把表达式计算结果通过赋值保存到特定的变量中。
指针通常用于实现动态数据结构,动态分配的元素没有名字,没有变量与之对应,无法直接引用,但是它们的地址可以通过某种方式计算出来。
此外处理数组时,虽然可以用下标引用,但是用指针表达式来引用更加方便,算法实现起来更简单。
再者是为了通用性和灵活性,比如函数指针,我可以定义一组相同函数原型的函数,根据需要指向特定的函数。比如说分情况处理,每种情况可以定义一个函数,这样主函数中只要设置函数指针指向特定的函数就可以了。真正的实现分布在各个具体的处理函数中,逻辑更为清晰,相互之间耦合较少,维护起来更容易。
还有就是回调函数,你写程序的时候要调用的函数还不存在。你可以通过检查函数指针是否为空,非空就调用,否则不调用。这样你的系统就具有可扩展性。
complayer
2012-02-27
打赏
举报
回复
p=NULL;
p=&p;
这个好像类型不一致吧。
int *p;
int **q;
q = &p;
世上本无事,庸人自扰之。
不要把指针想象得这么难,结果是自己给自己套上一副枷锁,故不自封,作茧自缚。
指针概念原本很简单,虽然*和&两个运算符比较特殊,真正的困难之处在于指针表达式的类型。就拿上面的例子来说,p的类型是int *,&p的类型是int **。
&&p有没有意义呢?呵呵!&p变成了一个R-Value,一个立即值,没有地址。
对于一个指针表达式弄清楚下面两点就行了:
1、这个指针表达式是L-Value还是R-Value。这很重要!
上面的例子来说p和*p是L-Value,p、*p,&p都可作为R-Value。
2、这个指针表达式的数据类型是什么。
*和&运算符作用于表达式会改变表达式的数据类型,这是指针表达式复杂的根源所在。
有人会拿汇编来说事,其实即便你精通了汇编也没用,因为汇编没有这么复杂的数据类型。BYTE, WORD, DWORD, QWORD就这些,还有有符号和无符号,这个要看具体的指令了。数据类型只在编译期间有效,到了汇编阶段这方面的信息已经没有了。当然你可以在程序里加上去,你就把这一串字节当作一个double处理,那就属于程序语义层面了,而不是语言层面。
i0073461
2012-02-27
打赏
举报
回复
太牛了。
[Quote=引用 14 楼 zhao4zhong1 的回复:]
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Linux或Unix下可以在用GDB调试时,看每句C……
[/Quote]
一线灵
2012-02-27
打赏
举报
回复
[Quote=引用 2 楼 saleayas 的回复:]
都不对!
[/Quote]
莫要欲盖弥彰, 危言耸听
muyi66
2012-02-27
打赏
举报
回复
p=NULL;
p=&p;
指向自身的指针可以实现,但没有意义。
complayer
2012-02-27
打赏
举报
回复
看了一下上面的系列回帖,写得好乱。主要是关于&操作符的返回值到底是lvalue还是rvalue,非常乱。
int a, b, *p1, **p2;
&a = &b; // 错误,虽然类型相同都是int *,但是因为&a是rvalue。
p1 = &a;
p2 = &p1;
&p1 = p2; //错误,虽然类型相同都是int **,但是因为&p1是rvalue
我们不能给一个rvalue表达式赋值,只能给lvalue表达式赋值。
加载更多回复(70)
【中航机考测试
感悟
】
以下程序运行后,输出的结果是(字符c的地址) main() {}因为d[]数组是
指针
数组,存放的是
指针
。如下程序输出结果是() int * * k , * j , i = 100;j = & i;k = & j;A.运行错误(我选的是A)B.100C.I的地址D.j的...
一位 70 后程序员的 26 个职场
感悟
有趣的一件事是,老板当时并不
知道
我已经“翅膀硬了”,想抵赖答应过的8000元项目奖金,年轻气盛的我在与之拍完桌子之后对其他工程师下令:“没有我的允许,谁也不能将电气图纸和电路原理图用于生产”(因为年经,...
【Java编程规范】阿里巴巴编程考试规范+真题答案+考试
感悟
可以说这个证书考的是经历的坎坷不小啊。好吧,我摊牌了,我一共考了5次才过。最后一次84分。 首先我在阿里云上看见这个认证规范,再加上博客中好多人都考了,而且描述的是考试非常简单。所以我也就试了一下。因为...
经典箴言和人生
感悟
人的一生中只有七次机会,平均每七年拥有一次,大概在25岁到75岁,第一次通常抓不到,因为太年轻,最后一次也抓不到,因为太老。中途还有2次因为自己错过,所以抓不到。所以对于人来说人真正才会有三次机会,人的...
程序员的几点
感悟
良好的习惯是尊敬师长,爱护同学,对人有礼貌;是不粗心,做事情不拖拉;还是爱护公物,不浪费粮食。为什么呢?因为拥有良好习惯,做一个品德高尚的人,懂得尊重别人,才会得到别人的尊重。我要努力地做到这些。我有...
C语言
69,369
社区成员
243,082
社区内容
发帖
与我相关
我的任务
C语言
C语言相关问题讨论
复制链接
扫一扫
分享
社区描述
C语言相关问题讨论
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章