2012-07-19 5 views
5

방금 ​​C++에서 불쾌한 버그가있었습니다. 그래서 레지스터와 값 목록을 구조체에 래핑 한 다음 해당 구조체를 배열로 초기화합니다. 그런데 실수로 {} 대신 ()을 입력했습니다.C++ 및 C의 괄호의 의미

#include <stdio.h> 

struct reg_val { 
     unsigned reg; 
     unsigned val; 
}; 

struct reg_val faulty_array[] = { 
     {0x5001, 0xff}, 
     {0x5580, 0x01}, 
     (0x5580, 0x02), //<- THIS LINE IS THE PROBLEM 
     (0x5589, 0x00), //<- AND THIS LINE 
}; 

struct reg_val good_array[] = { 
     {0x5001, 0xff}, 
     {0x5580, 0x01}, 
     {0x5580, 0x02}, 
     {0x5589, 0x00}, 
}; 

int main() 
{ 
     unsigned i; 
     unsigned faulty_size = sizeof(faulty_array)/sizeof(struct reg_val); 
     printf("Size of faulty array: %d\n", faulty_size); 

     for (i = 0; i < faulty_size; ++i) { 
       printf("faulty reg: %x val: %x\n", faulty_array[i].reg, 
         faulty_array[i].val); 
     } 

     unsigned good_size = sizeof(good_array)/sizeof(struct reg_val); 
     printf("\nSize of good array: %d\n", good_size); 
     for (i = 0; i < good_size; ++i) { 
       printf("good reg: %x val: %x\n", good_array[i].reg, 
         good_array[i].val); 
     } 
     return 0; 
} 

나는 C와 놀랍게도 더 익숙한이 여전히 ++ g 컴파일 오전 : 여기에 몇 가지 테스트 코드입니다

$ g++ -Wall array.cc 
array.cc:11: warning: left-hand operand of comma has no effect 
array.cc:12: warning: left-hand operand of comma has no effect 
array.cc:13: warning: missing braces around initializer for ‘reg_val’ 
$ ./a.out 
Size of faulty array: 3 
faulty reg: 5001 val: ff 
faulty reg: 5580 val: 1 
faulty reg: 2 val: 0  <-- the first value gets discarded as mentioned in the compiler warning 

Size of good array: 4 
good reg: 5001 val: ff 
good reg: 5580 val: 1 
good reg: 5580 val: 2 
good reg: 5589 val: 0 

이 코드는 분명 C 컴파일러로 컴파일 실패는, 무엇이입니다 C++의 차이점은 C++ 컴파일러를 (당당하게)이 코드를 허용합니까?

답변

4

가 귀하의 질문에 대답하기 위해, 내가 먼저 대답한다 : 왜이 ​​컴파일에 실패하는이 C에서 잘 컴파일 이후 사람들은 고려 상수가 아닌 이유는 나에게 아무 의미 C? 이 완벽하다

Size of faulty array: 4 
faulty reg: 5001 val: ff 
faulty reg: 5580 val: 1 
faulty reg: 5580 val: 2 
faulty reg: 5589 val: 0 

:

이제
struct reg_val faulty_array[] = { 
     {0x5001, 0xff}, 
     {0x5580, 0x01}, 
     0x5580, 0x02, //<- THIS LINE IS THE PROBLEM 
     0x5589, 0x00, //<- AND THIS LINE 
}; 

프로그램 출력 : 좋은 측정을 위해

initializer element is not constant 

,의는 C에서 {}의 드롭하자 : 음,이 때문에 컴파일에 실패 C 표준 (및 C++)에서 허용됩니다. C (및 C++) 평평한 중괄호를 사용하여 구조 요소를 초기화합니다 (다시 돌아올 것입니다). 정적 저장 기간을 가진 객체는 상수 표현식으로 초기화해야하거나 상수 표현식을 포함하는 집계 초기화 프로그램으로 초기화해야하므로 C에서 코드가 실패합니다. C는 (0x5580, 0x02)을 상수 표현으로 취급하지 않습니다.

이 (불행) C에서 컴파일 ++, 상수 표현으로 두 상수 식의 쉼표 연산자를 취급 ++ C는 그래서 당신의 코드를 더 좋아하기 때문에 ...

struct reg_val faulty_array[] = { 
     {0x5001, 0xff}, 
     {0x5580, 0x01}, 
     0x02, 
     0x00, 
}; 

이다, 물론, 허용 .

struct reg_val faulty_array[] = { 
     {0x5001, 0xff}, 
     {0x5580, 0x01}, 
     {0x02, 0x00}, 
}; 
+0

아, 고마워요. 내가 참조. 그건 의미가 있습니다. 그러나 gcc는 나에 대해 매우 만족스럽지 않은 것처럼 보입니다. '$ gcc -Wall array.c array.c : 13 : warning : initializer 주변에 괄호가 없다' – Lucas

+0

'-gall'을 사용하는'gcc'는'괄호를 제안하기 때문에'if (c = something())' 진리 값으로 사용 된 주위의 과제 '에 해당한다. ANSI C에 의해 허용 된 것이 경고를 생성하지 않는다는 것을 의미하지는 않습니다. –

+0

당신이 옳다면,'gcc -std = c89 -pedantic array.c'는 경고없이 컴파일됩니다. – Lucas

3

C++에는 양쪽 피연산자를 평가하고 왼쪽 피연산자의 값을 반환하는 쉼표 연산자가 있습니다. You can see it more clearly here.

그리고 C도 분명히 =) (감사합니다, @BenVoigt)

+2

질문은 "C와 비교하여 C++의 차이점은 무엇입니까?"대답은"쉼표 연산자 "가 아닙니다. –

+0

@BenVoigt : 저는 C를 모르지만, C++로 컴파일하는 이유를 설명하고 있습니다. C에서 컴파일하려고했는데 특정 부분이 실패했다고 가정했습니다. . – Ryan

+0

그리고 나는 C++에서 상수 피연산자가있을 때 컴파일 타임에이 표현식을 평가하려고한다고 가정하고 C는 C와 C++ 간의 오류 대 경고를 설명합니다. – antlersoft

4

당신이 그것을 C 컴파일하지 못할 것이라고 생각하게?

C++ : http://ideone.com/KLPh4 C : 당신의 경고에 http://ideone.com/VYUbL

주의하십시오. 나는 이것을 충분히 강조 할 수 없다. 이와 같은 실수를 잡는 데 도움이되는 경고가 있습니다.

글쎄, C의 오류 메시지는 차이를 완벽하게 알 수 있습니다. C는 이니셜 라이저를 임의의식이 아닌 상수로 요구합니다.

+4

C 랜드에서 컴파일하지 못하기 때문에 " 이니셜 라이저 요소가 상수가 아닙니다. "즉 :'(expr, expr)'이 상수 표현식 또는 집계 초기화가 아닙니다 –

+0

C 예제에서 '컴파일 오류'로 이데올로기 오류가 발생했습니다 – pmr

+0

@Travis : 감사합니다. –