鱼C论坛

 找回密码
 立即注册
查看: 2892|回复: 6

左值右值及*问题

[复制链接]
发表于 2022-9-16 09:20:54 | 显示全部楼层 |阅读模式
10鱼币
本帖最后由 MyGoddd 于 2022-9-16 09:48 编辑

求左值右值通俗解释,图片中的解释听的迷迷糊糊,而且C 语言的术语 lvalue 指用于识别或定位一个存储位置的标识符。这句话什么意思呢。 左值右值.png
语法糖问题,在指针中*p不是取值的意思么,但是在这里数组a【n】==*(a+n),也就是说其实*取值本质正是如此?那么在另一张图片中**(p+1)又是什么意思?是说*p是关于一维数组取值,**p是关于二维数组取值。又或者说语法糖与指针取值二者本质是相同的? 语法糖1.png 微信截图_20220916091652.png

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-9-16 16:44:10 | 显示全部楼层
本帖最后由 cnkizy 于 2022-9-17 15:23 编辑

*的含义是解引用,也就是通过地址取值,有了地址那么取多少个字节看你类型大小

设a为int数组,a的地址是0x100(也就是说a=0x100),a的元素个数是3,内容是6 7 8
也就是 int a[3] = {6, 7, 8};
那么:
        &a = 0x100
        a[0] = 6    &a[0] = 0x100
        a[1] = 7    &a[1] = 0x104
        a[2] = 8    &a[2] = 0x108


a[n] === a的地址+n*sizeof(int)长度的偏移,再取sizeof(int)个字节
那么a[2]就是一个指向了0x100 + 2*sizeof(int) = 0x108的地址,再取sizeof(int)个字节


*(a+n) 的意思:
        这里a是int数组,sizeof(int)=4, *a+n就是指向了 a的地址+n*4
        所以a[n] === *(a+n)
        设n=2,等价于
        int* pa = a + 2;
        int num = *pa; // 等价于 *(a+n)
        *(a+2) = *(0x100 + 2*4) = *(0x108) = 8


*a+n 的意思:
        别想太复杂,先*a:  a指向的地址 再取siezof(int)个字节, 然后这个值 + n
        设n=2
        *a+2 = 8 + 2 = 10

*a的意思:
        看懂上面,那么*a === *(a+0) === a[0]
       
       
**a又啥意思呢?
        这时候**a不能适用于int a[] 了,
        设 int a[2][3] = {
                1,2,3,
                4,5,6
        }

        *a 是 *a+0, *a+0 === a[0],  a[0]指向的是第二维数组中的第一个元素的地址
        a[0]指向的是1的地址,长度是sizeof(int[3]) 也就是 3*4 = 12个字节
        *a[0] 取出来是12个字节的东西, 是 一维int数组且长度为3
       
        那么看*(a[0] + n),        a[n]的类型是int,所以sizeof(int)=4,
        假设求a[1][2]的地址,那么应该是:找到a[1]的地址,再计算2的元素长度和偏移
        &a[1][2]  === *(a+1)+2
        a[1][2]  === *(*(a+1)+2)
       
       
同理出现了***a
        求a[1][2][3]的地址: *(*(a+1)+2)+3
        求a[1][2][3]的值: *(*(*(a+1)+2)+3)
       
下标运算符[]:
        关于[]这个标志也就是下标运算符,你完全可以看作地址取值的语法糖

       
       





想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-9-16 23:28:44 | 显示全部楼层
本帖最后由 howzyao 于 2022-9-16 23:35 编辑

int main()
{
    int sum=0;

    int *p=NULL;

    sum;    //这就叫做 右值

    sum++;  //这还叫做 右值

    p;      //这叫做 右值

    p = ∑ //这叫做 右值
    //此时,右值 和 上面的 右值 一模一样 只是有:
    //1,在 main 的内存空间里
    //2,右值前加了 取址符 操作了 右值 一次 但它 还是一个右值 只是这个右值
    //  在main中表达为了 一个地址 而不再是 int 了
    //3,右值 可以赋给 左边的变量 前提是 类型一致 现在左边的变量 是int类指针 专门操作
    //  int类的 内存空间 的 所以 可以被赋值
    //打印理解:
    cout<<"地址:"<<p<<" 它指向int空间中变量sum的值:"<<*p<<" sum的值:"<<sum<<endl;
    //以上,就是所谓的指针p 对 右值地址(这个地址就是空间是sum所占字节) 的 内存空间 进行了 "捆绑"
    //当然,这是我理解的,请广大坛友加以指正, 谢谢
    system("pause");
    return 0; // main end over there
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-9-16 23:29:50 | 显示全部楼层
本帖最后由 howzyao 于 2022-9-16 23:33 编辑

改了,容易理解么,可行的话,就拿去跑一下,就都清楚了.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-9-17 09:20:24 | 显示全部楼层
cnkizy 发表于 2022-9-16 16:44
*的含义是解引用,也就是通过地址取值,有了地址那么取多少个字节看你类型大小

设a为int数组,a的地址是0x1 ...

*是根据地址取值,同时数组首位也是个地址,然后加一之类的就是更改地址。我能否理解为这样呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-9-17 09:29:11 | 显示全部楼层
howzyao 发表于 2022-9-16 23:28
int main()
{
    int sum=0;

其实我有点看不懂,我才学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-9-17 11:31:04 | 显示全部楼层
本帖最后由 howzyao 于 2022-9-17 11:33 编辑
同时数组首位也是个地址,然后加一之类的就是更改地址

如果确定是数组的话,+1,就是下标+1,正是这样.可以通过 &a[x]来查看当前下标x的元素所 放的 内存地址.
结案.

上面搞清楚了后,关连紧密的另一案是下面的内容:
要注意的是:
当a[x]j中存放的是 1,2,3这样的实际数时 (可能叫做立即数,也是刚刚从坛里学到的)
那就说明 数组a 的每一个元素, 就是 一个 int变量.
这些变量,按照 int 在本机器中 固定的长度 依次排列的 所以 这时的下标每+1,就相当于
往后移动一个int长度,由此可见,此时每个元素都是有固定地址的,但这些固定地址,却没有指针,或者说,
这个地址,如oxABCD EEE1本身就是一个指针,但这个指针,并没有直观地赋给 自己定义的指针.

实验如下:

#include <iostream>

using namespace std;

int main()
{
    int a[3];
    a[1]=8;
    cout<<"可以看到 a[1]="<<a[1]<<endl;

    int *p=   &a[1]; //指向中间一个元素,p有自己的 内存地址x
                     //a[1] 也有自己的 内存地址y
                     //现在,在 内存地址 的维度 令y == x 了
                     //现在,开始看值是否一值:
    cout<<"可以看到 a[1]="<<*p<<endl;

    p;               //现在就等同了 &a[1]
                     //因为p是指针,cout函数 显示指针 变量的话
                     //默认是 直接输出 直接输出 指针的 值
                     //指针的值 是 地址 输出看看:
    cout<<" p ="<<p<<endl;

    //由于a[1]后面还有最后一个元素a[2]
    //偏后一下p看看
    p++;
    cout<<" p ="<<p<<" 此时p的地上和上个地址有什么变化"<<endl;
    //现在,p的地址发生了变化: +了4个字节.
    //现在,再来看看a[2]的地地是什么:
    cout<<"&a[2]="<<&a[2]<<" 此时右值 &a[2]的地上和上个地址有什么变化"<<endl;
    //可以发现,现在p的地址 和 a[2]的地址 是同一个地址,那么得出:
    //&a[2] == p
    //可以看到 a[2] 是一个没有被初始的int变量,这个变量也有地址,也可以
    //通过第三方指针来对访问,现在,来给这个地址中填写一个 整型值
    *p = 255;
    cout<<"  a[2] == *p == "<<*p<<endl;
    cout<<"&a[2] ==  p == "<<  p<<endl;  //请记住这两行的 * & 的使用规律. *取值 &取址

   
    //最后提一下,a[0]的地址,和p 一样,*a == 9 == a[0] 由此可见
    //数组名,就是一个指针变量,只是这个指针管理的内存长度,取决于下标
    //的值.


    cout << "Hello world!" << endl;
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-28 05:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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