左值右值及*问题
本帖最后由 MyGoddd 于 2022-9-16 09:48 编辑求左值右值通俗解释,图片中的解释听的迷迷糊糊,而且C 语言的术语 lvalue 指用于识别或定位一个存储位置的标识符。这句话什么意思呢。
语法糖问题,在指针中*p不是取值的意思么,但是在这里数组a【n】==*(a+n),也就是说其实*取值本质正是如此?那么在另一张图片中**(p+1)又是什么意思?是说*p是关于一维数组取值,**p是关于二维数组取值。又或者说语法糖与指针取值二者本质是相同的? 本帖最后由 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: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:33 编辑
改了,容易理解么,可行的话,就拿去跑一下,就都清楚了. cnkizy 发表于 2022-9-16 16:44
*的含义是解引用,也就是通过地址取值,有了地址那么取多少个字节看你类型大小
设a为int数组,a的地址是0x1 ...
*是根据地址取值,同时数组首位也是个地址,然后加一之类的就是更改地址。我能否理解为这样呢?
howzyao 发表于 2022-9-16 23:28
int main()
{
int sum=0;
其实我有点看不懂,我才学习{:10_266:} 本帖最后由 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]