[C언어 기초 문법] 질문이 있습니다.

박현규@Google의 이미지

int a = (1, 100);

이라고 입력하면 100이 대입되는 것은 확인했는데... 이런 문법을 공부한 적이 없어서 이 문법의 정체를 설명해 주실 분이 있나요...?

제가 이해하기로는...
그냥 마지막 변수가 대입된다... 정도...

라스코니의 이미지

, 연산자는 앞의 것을 실행하고 그 다음 것을 실행하란 이야기 입니다.
그래서
int a = 1;
a = 100;
의 효과가 있으므로 a 는 100이 됩니다.

, 연산자를 잘 이용하면 한 줄로 2개의 동작을 실행시킬수가 있어서 편리할 때도 있지만 코드 이해가 2배로 안될수도 있습니다. ^^

int a = ((b=func()), (b == EOF)? 1 : 100);

이런 식으로요.

박현규@Google의 이미지

감사합니다! 정확하게 이해한 건지 너무 궁금해서 달았네요... 왜 이런 문법을 만들었을까요?

익명 사용자의 이미지

괄호가 있어서 우선 순위가 달라집니다. (1,100) 이 100 으로 reduce되고 이게 a를 초기화하는데에 사용됩니다. 말씀하신 것과 같은 초기화 후 대입과는 의미가 다릅니다. 괄호 없이는 a가 1로 초기화되고 100은 최종적으로 아무 역할도 안합니다.

박현규@Google의 이미지

댓글을 보고 바로 Visual Studio로 달려가서 코드를 넣어 보았는데 아예 컴파일이 되지 않습니다. 제가 잘못 입력한 것일까요...?

int a = 100, 21;
익명 사용자의 이미지

안되네요. 콤마를 기준으로 양쪽 다 적법한 표현(expression) 이어서 될 줄 알았는데 안되는군요. 왜 안되는 지 궁금하네요.

bushi의 이미지

int a = 100;
int 21;
이 적법한 표현인가요 ?

 의 이미지

주어진 코드에서의 ,는 Comma operator입니다.
이 연산자는 우선 왼쪽 피연산자를 평가한 뒤, 그 값을 버립니다. (표준의 용어로는 evaluated as a void expression이라고 합니다.)
그 다음에 오른쪽 피연산자를 평가합니다.

연산 결과의 값과 타입은 오른쪽 피연산자의 것과 같습니다.

C언어에서 가장 우선순위가 낮은 연산자인 Comma operator의 역할은 분명합니다.
expression이 하나만 들어갈 수 있는 자리에 두 개 (혹은 그 이상) 넣고 싶을 때 주로 쓰이지요.
아래와 같은 용법을 볼 일이 가끔은 있을 겁니다.

int a, b;
 
for(a=0, b=10; a<b; a++, b--){
    printf("%d %d\n", a, b);
}

몇 가지 더.

라스코니 wrote:
, 연산자는 앞의 것을 실행하고 그 다음 것을 실행하란 이야기 입니다.
그래서
int a = 1;
a = 100;
의 효과가 있으므로 a 는 100이 됩니다.

(1, 100)는 1을 평가한 뒤 버리고, 오른쪽 피연산자의 값(100)과 타입(int)을 제공합니다.
결과적으로 a에 100이 대입되는 건 맞습니다만, Semantics 해석을 분명히 할 필요가 있을 것 같아서요.

익명 사용자 wrote:
괄호가 있어서 우선 순위가 달라집니다. (1,100) 이 100 으로 reduce되고 이게 a를 초기화하는데에 사용됩니다. 말씀하신 것과 같은 초기화 후 대입과는 의미가 다릅니다. 괄호 없이는 a가 1로 초기화되고 100은 최종적으로 아무 역할도 안합니다.

방금 전에 제가 지적한 내용과 같은 점을 지적하셨습니다만, 한 가지 틀리셨습니다.
int a = (1, 100);는 괄호를 빼면 컴파일조차 안 됩니다. 이후에 질문자님이 시도하신 int a = 100, 21; 역시, 컴파일 안 되는 게 정상입니다.

이후에 익명 사용자님(앞서 언급한 분과 같은 분인지는 모르겠습니다만)도 이 사실을 확인하신 것 같고, bushi님도 좋은 지적을 해 주셨습니다만, 제가 좀 더 긴 설명을 드릴 수 있겠군요.

C언어 소스 코드에 나타나는 Comma가 꼭 Comma operator인 것은 아닙니다. 예컨대...

int func(int a, int b){ // (1)
    int c, d; // (2)
    if (a)
        return func(a-1, b-1) // (3)
    else
        return b;
}

위 코드에서 (1), (2), (3)에서 쓰인 Comma는 Comma operator가 아닙니다.
C언어 Syntax에서 어떤 문법 구성요소의 list를 나타낼 때 구분자로 쓰기 위해 사용된 것이죠.

여기서 중요한 점. Comma operator의 사용이 위와 같은 list 구분자와 혼동될 수 있는 맥락에서는 Comma operator의 사용이 금지되어 있습니다.
구체적으로 어떻게 금지했는지는 C언어 표준에 BNF로 기술된 Syntax를 읽어 보셔야 하는데, 일단은 위와 같은 일반적인 서술로도 충분할 것 같군요.
C언어 표준에 이 부분에 대한 부연 설명이 되어 있습니다.

C11 std wrote:
As indicated by the syntax, the comma operator (as described in this subclause) cannot appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists of initializers). On the other hand, it can be used within a parenthesized expression or within the second expression of a conditional operator in such contexts. In the function call

f(a, (t=3, t+2), c)

the function has three arguments, the second of which has the value 5.

변수를 초기화하기 위한 expression 역시 이 제약에 묶여 있습니다. 왜 그래야 하는지 궁금하시다면...

int a = 0; // 전역 변수
 
void func(){
    int b = 0, a;
    // 지역 변수 a와 b를 선언한 것일까요, 아니면 b = (0, a)처럼 해석해서 b를 전역 변수 a로 초기화하는 것일까요?
    // 문법적 제약으로 인해 후자는 불가능하고, 확실히 전자입니다.
}

단, 표준에서도 언급했듯 expression을 괄호로 둘러싼 경우 그 안에서는 Comma operator를 사용할 수 있습니다. 그렇게 하면 혼동의 여지가 없어지니까요.
그래서 질문자님의 원래 코드 int a = (1, 100);는 사용 가능한 것입니다.

박현규@Google의 이미지

꼼꼼히 읽어보았습니다! 다들 너무 감사합니다!

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.