쉼표 연산자는 무엇을합니까? C에서 무엇입니까?

뭐라고합니까 ,연산자는 C에서 무엇입니까?



답변

표현식:

(expression1,  expression2)

먼저 expression1을 평가 한 다음 expression2를 평가하고 전체 표현식에 대해 expression2의 값을 리턴합니다.


답변

while루프 에서 가장 많이 사용되는 것을 보았습니다 .

string s;
while(read_string(s), s.len() > 5)
{
   //do something
}

작업을 수행 한 다음 부작용을 기반으로 테스트를 수행합니다. 다른 방법은 다음과 같이하는 것입니다.

string s;
read_string(s);
while(s.len() > 5)
{
   //do something
   read_string(s);
}


답변

콤마 연산자 왼쪽 피연산자를 평가하게는, 그 결과를 폐기하고 오른쪽 피연산자를 평가하고 그 결과가 될 것이다. 관용적 (A)에 사용되는 변수를 초기화 할 때 링크에서 언급 된 사용은 for루프 및 그 다음의 예이다 :

void rev(char *s, size_t len)
{
  char *first;
  for ( first = s, s += len - 1; s >= first; --s)
      /*^^^^^^^^^^^^^^^^^^^^^^^*/
      putchar(*s);
}

그렇지 않으면하지 많습니다 위대한 의 사용 쉼표 연산자는 그것을 읽고 유지하기 어려운 코드를 생성 할 수 남용이 용이하지만,.

로부터 초안 C99 표준에 다음과 같이 문법은 다음과 같습니다

expression:
  assignment-expression
  expression , assignment-expression

단락 2 는 다음 과 같이 말합니다.

쉼표 연산자왼쪽 피연산자는 void 표현식으로 평가됩니다. 평가 후 시퀀스 포인트가 있습니다. 그런 다음 올바른 피연산자가 평가됩니다. 결과 유형과 값이 있습니다. 97) 쉼표 연산자의 결과를 수정하거나 다음 시퀀스 포인트 이후에 액세스하려고하면 동작이 정의되지 않습니다.

각주 97의 말 :

쉼표 연산자는 lvalue를 생성 하지 않습니다 .

이는 쉼표 연산자 의 결과에 할당 할 수 없음을 의미합니다 .

쉼표 연산자가 우선 순위가장 낮 으므로 사용 ()이 큰 차이를 만들 수있는 경우가 있습니다. 예를 들면 다음과 같습니다.

#include <stdio.h>

int main()
{
    int x, y ;

    x = 1, 2 ;
    y = (3,4) ;

    printf( "%d %d\n", x, y ) ;
}

다음과 같은 출력이 나타납니다.

1 4


답변

쉼표 연산자는 두 표현식을 한쪽으로 결합하여 왼쪽에서 오른쪽 순서로 평가합니다. 오른쪽의 값은 전체 표현식의 값으로 반환됩니다.
(expr1, expr2)비슷 { expr1; expr2; }하지만 당신의 결과를 사용할 수있는 expr2함수 호출 또는 할당에.

다음 for과 같이 여러 변수를 초기화하거나 유지하기 위해 종종 루프에서 볼 수 있습니다 .

for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh)
{
    /* do something with low and high and put new values
       in newlow and newhigh */
}

이와는 별도로, 나는 항상 매크로에서 함께 진행해야하는 두 가지 작업을 마무리 할 때 다른 경우에는 “분노한”경우에만 사용했습니다. 우리는 네트워크에서 전송하기 위해 다양한 이진 값을 바이트 버퍼에 복사하는 코드가 있었고 포인터는 다음과 같은 위치에 유지되었습니다.

unsigned char outbuff[BUFFSIZE];
unsigned char *ptr = outbuff;

*ptr++ = first_byte_value;
*ptr++ = second_byte_value;

send_buff(outbuff, (int)(ptr - outbuff));

값이 shorts 또는 ints 인 경우 다음을 수행했습니다.

*((short *)ptr)++ = short_value;
*((int *)ptr)++ = int_value;

나중에 우리 (short *)ptr는 컴파일러가 신경 쓰지 않았지만 더 이상 l 값이 아니고 증가 할 수 없기 때문에 이것이 실제로 유효한 C가 아니라는 것을 읽었습니다 . 이 문제를 해결하기 위해 표현식을 두 가지로 나눕니다.

*(short *)ptr = short_value;
ptr += sizeof(short);

그러나이 접근법은 항상 두 진술을 모두 기억하는 모든 개발자에게 의존했습니다. 출력 포인터, 값 및 값 유형을 전달할 수있는 함수가 필요했습니다. 이것은 템플릿이있는 C ++이 아닌 C이므로 함수는 임의의 유형을 취할 수 없으므로 매크로를 설정했습니다.

#define ASSIGN_INCR(p, val, type)  ((*((type) *)(p) = (val)), (p) += sizeof(type))

쉼표 연산자를 사용하여 원하는대로 표현식이나 명령문으로 사용할 수있었습니다.

if (need_to_output_short)
    ASSIGN_INCR(ptr, short_value, short);

latest_pos = ASSIGN_INCR(ptr, int_value, int);

send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));

나는이 예제 중 어느 것이 좋은 스타일인지 제안하지 않습니다! 실제로 Steve McConnell의 Code Completefor루프 에서 쉼표 연산자를 사용하는 것에 대해서도 조언 하는 것을 기억 합니다. 가독성 및 유지 관리 성을 위해 루프는 하나의 변수로만 제어되어야하며 for행 자체 의 표현식 에는 루프 제어 코드 만 포함되어야합니다. 다른 여분의 초기화 또는 루프 유지 보수가 아닙니다.


답변

여러 문을 평가하지만 마지막 문만 결과 값으로 사용합니다 (rvalue, 생각합니다).

그래서…

int f() { return 7; }
int g() { return 8; }

int x = (printf("assigning x"), f(), g() );

x가 8로 설정됩니다.


답변

이전 답변에서 언급했듯이 모든 진술을 평가하지만 마지막 진술을 표현식의 값으로 사용합니다. 개인적으로 루프 표현식에서만 유용하다는 것을 알았습니다.

for (tmp=0, i = MAX; i > 0; i--)


답변

내가 유용하다고 생각한 유일한 장소는 표현식 중 하나 (아마도 init 표현식 또는 루프 표현식)에서 여러 가지 작업을 수행하려는 펑키 루프를 작성할 때입니다.

bool arraysAreMirrored(int a1[], int a2[], size_t size)
{
  size_t i1, i2;
  for(i1 = 0, i2 = size - 1; i1 < size; i1++, i2--)
  {
    if(a1[i1] != a2[i2])
    {
      return false;
    }
  }

  return true;
}

구문 오류가 있거나 엄격한 C가 아닌 것을 혼합 한 경우 용서하십시오. 나는 연산자가 좋은 형식이라고 주장하지는 않지만 그것을 사용할 수 있습니다. 위의 경우 아마도 while루프를 대신 사용하므로 init 및 loop의 여러 표현식이 더 분명합니다. (그리고 선언하고 초기화하는 대신 i1 및 i2 인라인을 초기화했습니다 …. blah blah blah.)