3항연산자에 대해 질문있습니다.

happyman의 이미지

C faq 3.16에 보면
((1) ? a : b ) = 111 ;
위와 같은 표현식자체가 불가능하다고 하는데 실제로 해보니 gcc에서 되는군요.
( 3항연산자는 lvalue를 만들지 못한다는...)
어떻게 이해해야 할까요
3항연산자가 gcc에서는 lvalue를 만든다고 봐야하나요.

akbar의 이미지

happyman wrote:
C faq 3.16에 보면
((1) ? a : b ) = 111 ;
위와 같은 표현식자체가 불가능하다고 하는데 실제로 해보니 gcc에서 되는군요.
( 3항연산자는 lvalue를 만들지 못한다는...)
어떻게 이해해야 할까요
3항연산자가 gcc에서는 lvalue를 만든다고 봐야하나요.

아니요
((1) ? a : b ) 의 연산결과는 변수 a 가 b 가 나와서
우연히 lvalue 가 된 것 뿐입니다.
이번에는 이렇게 해보세요
((1) ? a+1 : b+1 ) = 111 ;
컴파일이 될까요
((1) ? a+1 : b+1 ) 의 연산결과는 아까처럼 변수 a 가 b 가 아니라
거기에 1 을 더해준 값, 즉 이번에는 진짜 rvalue 입니다
3항연산자가 gcc에서는 lvalue를 만든다고 봐서는 안됩니다.
((1) ? a : b ) = 111 ; 의 형태는 대개의 컴파일러가 컴파일은 일단 할텐데
그렇다고 방심하지 마시고 매우 위험한 코드고 나쁜 습관이라는 점 알아두세요

cdpark의 이미지

akbar의 이미지

cdpark wrote:

gcc 확장 맞습니다.
http://gcc.gnu.org/onlinedocs/gcc-3.3.3/gcc/Lvalues.html

http://gcc.gnu.org/onlinedocs/gcc-3.3.3/gcc/Lvalues.html
좋은 내용이 많이 있네요
그러나 어쨋든 gcc 에서만 허용하는 확장이므로
문의 하신 내용은 이식성 문제를 피할 수가 없습니다.

노파심에서 한 번 더 얘기하면

gcc 에서
((1) ? a : b ) = 111 ;

이런 형태를 우연히 허용히 되나

((1) ? a+1 : b+1 ) = 111 ;

라는 형태는 진짜 rvalue 이므로 안되곘죠

이런 코드를 쓰시기 전에 한 번 쯤 생각해 보시기 바랍니다.

winner의 이미지

위의 documentation 에도 나와있듯이 C++ 에서는 표준에 허가되고 있습니다. 그런데 이것이 deprecated 라는 것은 처음 알았네요.
Accelerated C++ 에서도 나왔던 것인데 ':' 좌우의 두 개의 피연산자가 lvalue 일 때만 lvalue 입니다.

akbar 씨가 자꾸 실수하신 것인 rvalue 라고 써야 하는데 lvalue 라고 쓰셨네요. 문맥을 제가 이해하는 방식이 맞다면.. -_-

죠커의 이미지

C에서는 안됩니다. condition operator에서 C에서 lvalue(locator value)의 반환을 보장하지 않습니다. 그래서 gcc의 확장으로 보는 것이 옳다고 생각합니다.

반면에 C++에서는 아래의 경우에 한정해서 lvalue의 반환을 보장하고 있습니다.

Quote:
If the second and third operands are lvalues and have the same type, the result is of that type and is an lvalue.

akbar님이 말씀하신 ((1) ? a+1 : b+1 )는 a+1과 b+1이 일반적인 산술식으로 최급되어서 a+1이라는 계산의 값을 condition operator가 반환할 것입니다. 이때 a는 lvalue가 아닌 rvalue(value of an expression)이 쓰여야 된다고 봅니다.

akbar의 이미지

winner wrote:
위의 documentation 에도 나와있듯이 C++ 에서는 표준에 허가되고 있습니다. 그런데 이것이 deprecated 라는 것은 처음 알았네요.
Accelerated C++ 에서도 나왔던 것인데 ':' 좌우의 두 개의 피연산자가 lvalue 일 때만 lvalue 입니다.

akbar 씨가 자꾸 실수하신 것인 rvalue 라고 써야 하는데 lvalue 라고 쓰셨네요. 문맥을 제가 이해하는 방식이 맞다면.. -_-


CN wrote:

akbar님이 말씀하신 ((1) ? a+1 : b+1 )는 a+1과 b+1이 일반적인 산술식으로 최급되어서 a+1이라는 계산의 값을 condition operator가 반환할 것입니다. 이때 a는 lvalue가 아닌 rvalue(value of an expression)이 쓰여야 된다고 봅니다.

제가 왜 rvalue 를 써야 할 자리에 lvalue 를 썼는 지 모르겠네요.
그래서 지금은 수정해 놓았습니다.(^^)
또한 C++ 이 조건연산자의 "lvalue" 를 허용한다는 것도
C++ 사양을 펼치지 않더라도 C++ 적인 생각을 조금만 했더라면
알 수 있었을 텐데... 이 점을 지적한 winner 씨에게 감사드립니다.
덧붙이자면
C++ 에서는 해당 연산 이전에 어떤 값이 메모리에 잡혀 있으면
lvalue 자리에 올 수 있도록 허용합니다.

따라서 정수를 인수로 받는 함수를 가정했을 때
C 프로그래머가 본다면 다소 기형적인 듯한 아래의 코드가 가능합니다.

// lvalue = rvalue 나 lvalue += rvalue 형태

f_test1(1)(2)(4)(5) += f_test2(5)(6)(7)(9) ;

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.