【问题标题】:How to avoid "lvalue required as unary ‘&’ " error in one line?如何避免一行中出现“lvalue required as unary ‘&’”错误?
【发布时间】:2021-06-07 05:35:32
【问题描述】:

我知道如何简单地避免lvalue required as unary ‘&’ 错误(如here

我尝试做的是避免在一行中出现此错误。 为什么?我定义了很多 const,并且在我正在处理的一些写得不好的代码中,这些 const 用于初始化。我不想每次使用时都定义一个中间变量...

在下面的例子中我需要中间值't'

int  * p;
const int q = 88;
int t = (int)q; //works but I have to add for each time I used q, an intermediate variable.
p = &t;
printf("p: %u\n",*p);

在以下示例中,我不需要中间值 't'(但它不起作用)

int  * p;
const int q = 88;
p = &((int)q); //what I would like to do but raises:  error: lvalue required as unary ‘&’ operand
printf("p: %u\n",*p);

有单线方式吗? 使用#defines 可能是一个提示...

注意:我不希望在我的编译中出现任何警告,因为我正在纠正 MISRA 违规: Cast from 'const int *' removes 'const' qualifier (MISRAC2012-RULE_11_8.a)

注意:p 没有声明为 const int,因为 p 稍后会被修改。 p 使用 i 来初始化自己。


如果变量很简单,则“StoryTeller - Unslander Monica”给出的解决方案有效:p = &((int){i});

但这不适用于结构:

    typedef struct
    {
        int i;
        int j;
    }struct_t;
    
    const struct_t q = {.i=12,.j=88};
    printf("q: %u - %u\n",q.i,q.j);
    
    struct_t  * p = &((struct_t){q});
    printf("p: %u - %u\n",p->i,p->j);

其中的编译引发error: incompatible types when initializing type ‘int’ using type ‘struct_t {aka const struct }’

【问题讨论】:

  • 你必须转换&的结果... (int *)(&i)
  • 不,它会引发 MISRA 错误
  • 这个问题缺少一个重要的细节:为什么p 没有声明const int * 这样可以以正确的方式解决问题。
  • @GuillaumeD 您是稍后修改p,还是*p?如果是前者,可以定义为const int *
  • @GuillaumeD,也可以为结构类型形成复合文字。事实上,这是他们的主要用例。对术语(“复合文字”)进行一些研究。这一切确实有相当强烈的代码气味,但你没有提供足够的东西让我们提出更好的替代方案。

标签: c pointers casting initialization constants


【解决方案1】:

(int)i 这样的强制转换表达式确实不是左值。然而,compound literal一个左值:

p = &(int){i};

它本质上会生成一个具有自动存储持续时间的匿名整数,该整数从 i 初始化,并一直持续到封闭范围结束。

所以你也得到了一个有效的指针。


使用结构会稍微改变游戏环境。由于初始化列表的语义在标量和聚合之间有所不同。但这并不意味着我们不能以统一的方式工作。只需创建一个数组(包含 1 个元素),因此我们总是初始化一个封闭聚合。现在两个代码 sn-ps 都可以工作了

// p = (int[]){i};
struct_t *p = (struct_t[]){q};

虽然转换为指针是隐式的(这可能会引发争论)。

【讨论】:

  • 好的,但是这段代码的目的是什么?
  • @KonradRudolph - 创建一个对象之一,该对象通常通过指针传递给函数。
  • 正是我正在寻找的......目的?纠正 misra 违规行为!
  • @StoryTeller-UnslanderMonica 为什么不为此使用常规自动变量?
  • @KonradRudolph - 因为它需要有一个名字。并非所有事物都值得命名。 C++ 在语言层面解决了这个问题,我们可以将临时绑定到 const 左值引用。但是 C 没有引用。并且地址运算符只能应用于左值。所以 C99 引入了未命名的左值。这就是它的全部内容。
猜你喜欢
  • 1970-01-01
  • 2019-11-09
  • 1970-01-01
  • 2020-07-13
  • 1970-01-01
  • 2017-09-28
  • 2016-11-14
  • 1970-01-01
  • 2013-06-20
相关资源
最近更新 更多