본문으로 바로가기

lvalue required as increment operand

category Language/C 2017. 2. 22. 14:44

What is lvalue?


해당 에러 메세지에 대해 알아보기 전에 lvalue에 대해 간단히 알아보기 위해 MSDN의 lvalue에 대한 정의를 살펴보자.


An lvalue refers to an object that persists beyond a single expression. You can think of an lvalue as an object that has a name. All variables, including nonmodifiable (const) variables, are lvalues. An rvalue is a temporary value that does not persist beyond the expression that uses it.

- MSDN -



MSDN에서 말한 lvalue란 하나의 표현식을 넘어서 존재하는 object이며 쉽게 말해 우리가 값을 할당하고, 변경하며 사용하는 variable인 것이다. 아래의 변수가 lvalue이며 "1 + 1"이라는 표현식의 결과가 rvalue라고 할 수 있을 것이다.


lvalue_var = 1 + 1;




lvalue error

내 경우에는 type cast를 사용한 표현식에 증가 연산자(Increment operator)를 사용하여 해당 에러가 발생하였다. 다음의 코드는 컴파일 시 "lvalue required as increment operand" 에러메세지를 출력하게 된다.


int main(int argc, char **argv, char **envp)

{

        int l = 0;


        l++;

        l = 0;


        //l = ((long int)l) + 1;

        l = ((long int)l)++;


        return 0;

}


$ gcc cast.c

cast.c: In function ‘main’:

cast.c:9:19: error: lvalue required as increment operand

  l = ((long int)l)++;

                   ^



type castpostfix increment operator간의 우선순위는 후자 쪽이 더 우선한다. 그러므로 괄호를 한번 더 사용하지 않는다면 ++이 먼저 적용되므로 에러가 나지 않지만 type cast를 우선하게 만든다면 에러가 발생하게 된다. 즉 type cast의 결과는 lvalue가 아니라는 의미인 것 이다.


그렇다면 type cast가 어떻게 처리되는지 알기 위해 위의 주석처리를 서로 바꿔서 에러가 나지 않게 하고 해당 assembly 코드를 살펴보았다. 해당 코드를 살펴보면 type cast가 된 값은 레지스터에서 연산되므로, 변수를 의미하는 lvalue가 아니게 된다. ++ 연산자는 lvalue를 operand로 삼으므로 에러가 발생하게 되는 것이다.


(gdb) disas main

Dump of assembler code for function main:

   0x00000000004004ed <+0>:     push   %rbp

   0x00000000004004ee <+1>:     mov    %rsp,%rbp

   0x00000000004004f1 <+4>:     mov    %edi,-0x14(%rbp)

   0x00000000004004f4 <+7>:     mov    %rsi,-0x20(%rbp)

   0x00000000004004f8 <+11>:    mov    %rdx,-0x28(%rbp)

   0x00000000004004fc <+15>:    movl   $0x0,-0x4(%rbp)

   0x0000000000400503 <+22>:    addl   $0x1,-0x4(%rbp)

   0x0000000000400507 <+26>:    movl   $0x0,-0x4(%rbp)

=> 0x000000000040050e <+33>:    mov    -0x4(%rbp),%eax

   0x0000000000400511 <+36>:    add    $0x1,%eax

   0x0000000000400514 <+39>:    mov    %eax,-0x4(%rbp)

   0x0000000000400517 <+42>:    mov    $0x0,%eax

   0x000000000040051c <+47>:    pop    %rbp

   0x000000000040051d <+48>:    retq

End of assembler dump.



그러므로 type cast를 사용할 때 이러한 에러 발생 여부를 염두해 두고 사용해야 될 듯 싶다.




참고