You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

传递解引用指针地址到字符串偏移时的编译错误原因及解决方法

问题解答:左值报错原因及无临时变量传递二级指针方案

让我来一步步拆解你的问题,帮你搞清楚报错的根源,以及怎么在不声明临时变量的情况下解决这个问题。

一、为什么编译器会报lvalue required as unary '&' operand

简单来说,&(取地址)操作符要求它的操作数必须是左值(lvalue)——也就是一个有固定内存位置、可以被修改或取地址的对象。而你写的*str + x是一个右值(rvalue):它是计算出来的临时结果(字符串起始地址偏移x字节后的地址值),这个临时值没有持久的内存存储位置,只是一个临时的数值,所以编译器不允许对它取地址。

举个更直观的例子:你写&(5)也会报同样的错,因为5是常量右值,没有内存地址可以取;同理*str + x是临时计算出来的地址值,属于右值,自然不能用&取地址。

二、不用临时变量传递二级指针的可行方案

既然临时变量p能工作(因为它是左值),那我们可以用C99引入的**复合字面量(Compound Literal)**来创建一个匿名的左值,达到不用显式声明变量的目的。

方案1:直接创建char*类型的复合字面量

这是你代码里已经验证过的可行写法:

int temp = read_string(&(char *){ *buffer + bytes }, size - bytes, 0);

这里的(char *){ *buffer + bytes }就是一个复合字面量,它会在栈上创建一个匿名的char*变量,变量的值是*buffer + bytes(也就是你想要的偏移后的地址)。这个匿名变量是左值,所以&可以正常取它的地址,得到的char**刚好匹配read_string的参数类型。

你代码里的另一种写法&(*buffer)[bytes]其实和*buffer + bytes是等价的,只是语法形式不同,本质一样。

方案2:用数组复合字面量隐式转换

还有一种写法是利用数组到指针的隐式转换:

int temp = read_string( (char*[1]){ *buffer + bytes }, size - bytes, 0);

这里(char*[1]){ ... }创建了一个包含单个char*元素的数组,数组名会自动转换为指向数组首元素的指针(也就是char**类型),同样能满足函数的参数要求。

为什么你尝试的buffer + bytes不行?

你代码里的这个写法是典型的指针类型理解错误:bufferchar**类型(二级指针),buffer + bytes相当于把二级指针本身偏移了bytes * sizeof(char*)字节,这完全不是你想要的——你需要的是对*buffer(一级指针)做偏移,然后取它的地址,而不是偏移二级指针本身,所以这个写法会导致错误的内存访问。

三、结合你的模拟代码验证

你的代码模拟了分段接收字符串的场景(用randomizer模拟无法一次接收全部数据),用复合字面量的写法可以完美替代临时变量p,同时保持代码简洁。两种复合字面量的写法都能正常运行,最终正确拼接出完整的字符串。


内容的提问来源于stack exchange,提问作者Edenia

火山引擎 最新活动