需要L值吗? C编程位模式

时间:2012-07-25 10:52:00

标签: c bit-manipulation lvalue

void InsertA(SET *A,int elem)
{
    if( isMember(*A,elem) == false)
    {
    *A = *A || 1<<elem;; /*it says its in this row*/
    }
}

/ *错误:函数InsertA中需要左值 对这个人的任何想法?诺布在这里

* /

3 个答案:

答案 0 :(得分:2)

在此声明中:

*A = *A || 1<<elem;; /*it says its in this row*/

我们有这些运算符*,=,||,<<

现在查看

的优先顺序表
Precedence    Operator   operation                  associativity 
               --------   ---------                 ----------------
3                  *       Indirection (dereference)       R to L
7                  <<       Bitwise left shift             L to R
14                 ||       Logical OR                     L to R
16                 =       Direct assignment               R to L

让我们看看会发生什么:

1)首先进行间接。有两个。他们将权利归于左派。这意味着将首先执行正确的一个。重要的是要理解这里有两个解除引用运算符,以后在遇到=运算符时会有不同的考虑。

2)在1上执行一个小的左移。 3)将使用*A和按位移位的结果执行逻辑OR。它可以评估零或非零。 4)此零/非零值将分配给*A。此处*A可以在=运算符的上下文中视为左值。如果你考虑这个问题,就会导致模棱两可。因为我们经常将*A的解除引用操作视为要使用的rvaluevalue。实际上它是一个有效的lvalue,它将被隐式转换为rvalue(这是在value指向的地址存储A时返回的)。否则*A只是内存中一个对值开放的容器。

所以事情是你的表达是未定义的,并且没有任何意义为什么你将逻辑值放入*A。如果使用二进制or而不是逻辑,那将更有意义。

让我们这样做:

我们的优先级表中有一个新条目

Precedence OP   OPeration        Associativity 
12         |    Bitwise OR          L to R

只有在执行按位OR时,才会在步骤3中进行更改。

让我们举个例子

让我们说elem = 3. A指向数组{1,2,3,3,4}

1)'*将执行A'。它只会计算执行处理器的loadstore指令所需的“偏移量”。

2)我们将得到一个恒定的位模式:1 << 3 = 1000 3)现在|我们需要rvalues作为两个操作数。所以现在将执行load指令来获取存储在存储器中的值。说出它的2。所以我们会得到0010 | 1000 = 1010 4)将执行存储指令将该位模式放入存储器中,使得数组看起来像{1,A,3,3,4}

过多冗长的解释:我认为如果未来的用户试图找到如何通过语言规则剖析复杂表达式,这可能会有所帮助。

答案 1 :(得分:0)

如评论中所述,代码应该编译。 但看起来你想在int设置一点,所以我怀疑,你真的想要|而不是||。 所以你应该做

*A |= 1<<elem;

答案 2 :(得分:0)

||是一个逻辑运算,而不是一个按位运算。您是否尝试将其更改为??

每当你做A =你就有可能创造一个临时A,与* A相同。注意使用=运算符并查找如何禁用复制构造函数。

您可以使用| =运算符。 A | =(1&lt;&lt; whatever)

编辑:确保您没有在C ++模式下使用C ++编译器编译C代码。 GCC有一个C开关,它取决于你的构建环境。