吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 519|回复: 4

[C/C++] C语言指针和左值

[复制链接]
学编程的闹钟 发表于 2024-3-8 14:48 | 显示全部楼层 |阅读模式

本帖最后由 学编程的闹钟 于 2024-3-8 14:49 编辑

首先我们要知道内存是如何存放变量的:通过变量名对变量进行访问和存储是为了方便程序员而设计的,其实在内存中完全没有存储变量名的必要。因为编译器知道具体每一个变量名对应的存放地址,所以当你读取某个变量的时候,编译器就会找到变量名所在的地址,并根据变量的类型读取相应范围的数据。通俗的来说就是变量名就是个地址,存这个地址存放的是一个不同类型的值。

我们先通过变量名来访问一个整型变量的地址,代码如下:
[C++] 纯文本查看 复制代码
#include<stdio.h>
int main(void)
{
    int a=77;//当然这里不被赋值也可以。
    printf("%d",&a);//这里在a前面加了个&取地址符,得到的是a的地址。
    printf("%p",&a);//这里%p是通过十六进制输出地址,上面一行代码则是十进制。
    return 0;
}

fakename.png

上面这段代码十进制的地址是:6356764。十六进制地址是:0060FF1C。有些怀疑的朋友可以通过计算器转换试试哈。每次地址都不会一样,所以最好先通过查找一个int变量的地址,在用那个地址-4得到我们要存放值的地址,这样能最少与当前地址之前的存放的东西冲突,就会报错。

好,接下来我们就用十进制的地址的方法给大家演示。上面我们知道了一个十进制地址:6356764。因为int类型占4字节,所以我们就6356764-4=6356760。我们就用这个地址来做演示。

我们想把一个值存放到一个地址里面去都先想的是这样:
[C++] 纯文本查看 复制代码
#include<stdio.h>
int main(void)
{
    6356760=77;//我们想把6356760想成是一个地址,而编译器只会认为这是一个常量,所以会报错。
    return 0;
}

fakename.png

当然上面这段代码肯定是错误的,因为编译器根本不知道6356764是一个地址,它只会认为这是一个常量。

上面报错信息为:lvalue required as left operand of assignment。翻译过来就是:左值必须作为赋值的左操作数。

那我们就强制转换为地址,也就是指针类型,代码如下:

[C++] 纯文本查看 复制代码
#include<stdio.h>
int main(void)
{
    (int*)6356760=77;//这里强制转换成了整型指针类型。
    printf("%d\n",(int*)6356760);//我们想要输出这个地址的值,也就是77。
    return 0;
}

fakename.png

有些朋友可能会认为这样就可以运行了,但其实不然。

它还是会报错:lvalue required as left operand of assignment。翻译过来就是:左值必须作为赋值的左操作数。

是不是觉得还差了啥,没错差个解引用,没有这个符号怎么能给内存赋值呢。代码如下:

[C++] 纯文本查看 复制代码
#include<stdio.h>
int main(void)
{
    *(int*)6356760=77;//这里强制转换成了整型指针类型,再用取地址符分配内存。
    printf("%d\n",*(int*)6356760);//我们想要输出这个地址的值,也就是77。
    return 0;
}

fakename.png

这样代码即没报错,也没失败,成功的打印出了77。

所以这里没有变量名来分配地址也能成功分配地址。所以不要死脑筋。不过有时那个地址被占用了,要多多换换地址就行。

上面有两个错误的代码中的报错都是:lvalue required as left operand of assignment。翻译过来就是:左值必须作为赋值的左操作数。

那么到底什么是左值(lvalue)和右值(rvalue)呢?

你会经常看到 lvalue 这个词。一般出现在各种书籍中,更频繁遇到的是在你的错误提示中。

一般你会看到这个错误是因为你的代码类似这么写:

[C++] 纯文本查看 复制代码
#include<stdio.h>
int main(void)
{
    int i;
    5=i;
    return 0;
}


一些朋友可能想当然的就觉得左值(lvalue)指的就是赋值运算符左边的那个值,而右值(rvalue)当然就是右边那个值啦。所以我们叫它们为“左值”和“右值”。

事实上这样理解并不全面,并且常常容易犯思想上的错误。

首先,我们找到 C 语言的作者问问究竟,他是这么说的:

《The C Programming Language》翻译:《C程序设计语言》

"An object is a manipulatable region of storage; an lvalue is an expression referring to an object.

The name 'lvalue' comes from the assignment expression E1 = E2 in which the left operand E1 must be an lvalue expression."

上面书中内容翻译为:

对象是可操纵的存储区域;左值是指对象的表达式。

名称“左值”来自赋值表达式E1=E2,其中左操作数E1必须是左值表达式

因为C语言是在不断发展的,毕竟老头的这本书说的是C语言的原型,自1988年第二版之后就没有再出新版了。而C的标准则经历了 K&RC,C89,C90,C99,C11 的迭代。
那我们找来了目前最广泛使用的 C99 标准:

The name "lvalue" comes originally from the assignment expression E1 = E2, in which the left operand E1 is required to be a (modi?able) 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".

上面书中内容翻译为:

“左值”的名称最初来自赋值表达式E1=E2,其中左操作数E1必须是(可调整的、可修改的)左值。它可能更被认为是表示对象“特定位置的值”。有时所谓的“左值”在这个国际标准中被称为“表达式的值”。

所以,单纯用左边(left-value)和右边(right-value)来理解是不全面的。请尝试执行下边代码:

[C++] 纯文本查看 复制代码
#include<stdio.h>
int main(void)
{
    int a=5;
    ++(a++);
    return 0;
}


你会得到下边错误提示:lvalue required as increment operand。翻译为:递增操作数需要左值。

在这里如果你认为lvalue只是赋值运算符左边那个值,那这个错误提示就无法理解了。但是如果你知道lvalue是用于识别或定位存储位置的标识符,那么就好解释了:

(a++)是先将变量a的值(5)做为整个表达式的值返回,再将a自增(类似于a=a+1)。
所以这里++(a++);,相当于++(5),a=a+1;
这个当然要报错,5是一个常量,当然不能执行5=5+1。

C 语言的术语lvalue指用于识别或定位一个存储位置的标识符。(注意:左值同时还必须是可改变的)。

除了左值其实还有右值吧,没错,其实rvalue的发明完全是为了搭配lvalue,rvalue你可以理解为readable value,即任何可读取的值都被认为是右值(非左值)。

fakename.png

评分

参与人数 2HB +2 THX +1 收起 理由
绿色耀西 + 1 + 1
蜗牛跑了快 + 1 [吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意!

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
书香 发表于 2024-3-8 17:19 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
 楼主| 学编程的闹钟 发表于 2024-3-8 17:29 | 显示全部楼层

书香 发表于 2024-3-8 17:19
这篇文章是介绍指针和左值的吗

是的呀.

点评

书香”点评说:
可以出一个系列的图文课程  详情 回复 发表于 2024-3-8 18:24
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
书香 发表于 2024-3-8 18:24 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
 楼主| 学编程的闹钟 发表于 2024-3-9 09:15 | 显示全部楼层

书香 发表于 2024-3-8 18:24
可以出一个系列的图文课程

嗯,以后会出的
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表