MyGoddd 发表于 2022-9-16 09:20:54

左值右值及*问题

本帖最后由 MyGoddd 于 2022-9-16 09:48 编辑

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

cnkizy 发表于 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 = {6, 7, 8};
那么:
        &a = 0x100
        a = 6    &a = 0x100
        a = 7    &a = 0x104
        a = 8    &a = 0x108


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


*(a+n) 的意思:
        这里a是int数组,sizeof(int)=4, *a+n就是指向了 a的地址+n*4
        所以a === *(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
       
       
**a又啥意思呢?
        这时候**a不能适用于int a[] 了,
        设 int a = {
                1,2,3,
                4,5,6
        }

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

       
       





howzyao 发表于 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
}

howzyao 发表于 2022-9-16 23:29:50

本帖最后由 howzyao 于 2022-9-16 23:33 编辑

改了,容易理解么,可行的话,就拿去跑一下,就都清楚了.

MyGoddd 发表于 2022-9-17 09:20:24

cnkizy 发表于 2022-9-16 16:44
*的含义是解引用,也就是通过地址取值,有了地址那么取多少个字节看你类型大小

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

*是根据地址取值,同时数组首位也是个地址,然后加一之类的就是更改地址。我能否理解为这样呢?

MyGoddd 发表于 2022-9-17 09:29:11

howzyao 发表于 2022-9-16 23:28
int main()
{
    int sum=0;


其实我有点看不懂,我才学习{:10_266:}

howzyao 发表于 2022-9-17 11:31:04

本帖最后由 howzyao 于 2022-9-17 11:33 编辑

同时数组首位也是个地址,然后加一之类的就是更改地址
如果确定是数组的话,+1,就是下标+1,正是这样.可以通过 &a来查看当前下标x的元素所 放的 内存地址.
结案.

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

实验如下:

#include <iostream>

using namespace std;

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

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

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

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

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


    cout << "Hello world!" << endl;
    return 0;
}
页: [1]
查看完整版本: 左值右值及*问题