표준을 따르고 그 문제에 대해 C 표준을 취해야합니까?


17

Stack Overflow에는 항상 C 표준에 대해 이야기하는 경험 많은 사람들이 있습니다. 사람들은 나를 위해 일하더라도 휴대용이 아닌 솔루션을 좋아하지 않는 것 같습니다. 좋아, 나는 표준을 따라야하지만 프로그래머의 창의력에 걸쇠를 두지 않습니까?

표준을 준수함으로써 얻을 수있는 구체적인 이점은 무엇입니까? 특히 컴파일러는 표준을 약간 다르게 구현할 수 있습니다.


7
"표준"이 의미하는 바를 명확하게 설명해 주시겠습니까? 표준에 의해 정의되지 않은 행동을 생각하지 않습니까? 아니면 확장 / 컴파일러 기능을 사용하지 않습니까? 아니면 스타일 규칙?
ikh

1
@ikh 그는 ISO C 표준 (C90, C99, C11)을 취하고 있습니다.
Aseem Bansal

9
영어 문법과 어휘를 사용하여 영어로 글을 쓰거나 말하면 창의력에 걸림돌이된다는 말과 같습니다. 물론 사람들은 일관성을 희생하면서 규칙을 어기면 훌륭한 일을 할 수 있지만 영어의 "표준"을 지키면서 수백만 권의 책을 쓸 수 있습니다.
Avner Shahar-Kashtan

"사람들이 나를 위해 일하더라도 휴대 할 수없는 솔루션을 좋아하지 않는 것 같습니다"라는 예를 추가 할 수 있습니까?
BЈовић

1
@PHIfounder 마지막 ​​사건을 해결하기 위해 main에서 리턴을 생략 할 수 있습니다. 암시 적으로 0을 리턴합니다.
Daniel Gratzer

답변:


45

표준을 고수하는 것이 좋은 이유는 몇 가지가 있습니다.

  1. 컴파일러에 갇히게되면 짜증이납니다. 자신의 의제를 가진 개발자 그룹의 자비에 전적으로 달려 있습니다. 그것들은 분명히 당신이나 다른 것을 얻지 못하지만 컴파일러가 최적화, 새로운 기능, 보안 수정 등에 뒤쳐지기 시작하면 너무 나빠집니다. 당신은 붙어있다. 극단적 인 경우 일부 회사는 자신이 의존 한 도구를 패치하기 시작해야합니다. 이것은 다른 작업 도구가있을 때 엄청난 돈과 시간 낭비입니다.

  2. 플랫폼에 갇히게되면 더 힘들어집니다. Linux에서 소프트웨어를 추진하고 있고 시장이 실제로 있다는 사실을 알고 Windows로 전환하고 싶다면 코드에서 얻은 모든 이식 불가능한 해킹을 멋지게 변경하는 데 많은 시간이 걸릴 것입니다. GCC와 MSVC를 모두 사용합니다. 그런 것을 중심으로 몇 가지 핵심 디자인이 있다면 행운을 빕니다!

  3. 이전 버전과 호환되지 않는 변경 사항이 가장 어려워졌습니다. 표준은 코드를 위반하지 않습니다 (파이썬 무시). 그러나 임의의 컴파일러 작성자는 실제로이 구현 특정 애드온이 문제가되지 않는다고 결정할 수 있습니다. 당신이 그것에 의존한다면, 당신은 그것이 오래 된 오래된 버전이 무엇이든 붙어 있습니다.

따라서 표준을 고수 하는 가장 중요한 메시지 는보다 유연 합니다. 언어가 더 제한적이지만 더 많은 언어가 있습니다

  • 도서관
  • 지원 (사람들은 모든 복잡한 컴파일러 관련 핵이 아니라 표준을 알고 있음)
  • 사용 가능한 플랫폼
  • 성숙한 도구
  • 보안 (미래 증명)

미묘한 균형이지만 표준을 완전히 무시하는 것은 실수입니다. 이식성이없는 방식으로 구현 될 수있는 추상화에 의존하도록 C 코드를 구성하는 경향이 있지만 추상화에 의존하는 모든 것을 변경하지 않고 투명하게 이식 할 수 있습니다.


+1 fair : :, thanks ... 컴파일러가 표준에서 약간 벗어난 방식을 심각하게 혼동하여 엄격하게 준수하는 것에 대해 회의적으로 느끼게 만들었습니다.
0decimal0

6
정의되지 않은 행동은 아마도 꽤 짜증납니다. c를 사용하면 표준을 엄격하게 따르지 않으면 UB에 쉽게 들어갈 수 있습니다.
코드 InChaos

@CodesInChaos 합의되고 정의되지 않은 동작은 미친 최적화를 허용하기 때문에 훌륭하지만 다른 디버깅에서는 가능합니다.
Daniel Gratzer

6

표준은 프로그램의 의미를 정의하는 컴파일러와 사용자 간의 일종의 "계약"입니다. 프로그래머로서, 우리는 종종 언어의 작동 방식에 대한 특정 정신 모델을 가지고 있으며,이 정신 모델은 종종 표준과 상충됩니다. (예를 들어, C 프로그래머는 종종 포인터를 대략 "메모리 주소를 나타내는 정수"라고 생각하기 때문에 메모리를 나타내는 정수로 수행 할 수있는 포인터에 대해 산술 / 변환 / 조작을 수행하는 것이 안전하다고 가정합니다 이 가정은 표준과 일치하지 않으며 실제로 포인터로 수행 할 수있는 작업에 대해 매우 엄격한 제한을가합니다.)

그렇다면 자신의 정신 모델보다는 표준을 따르는 것의 장점은 무엇입니까?

간단히 말해, 표준이 정확하고 자신의 정신 모델이 잘못되었다는 것입니다. 멘탈 모델은 일반적으로 모든 컴파일러 최적화가 비활성화 된 상태에서 일반적으로 시스템에서 작업이 수행되는 방식을 간략하게 보여줍니다. 컴파일러 공급 업체는 일반적으로 특히 최적화와 관련하여이를 준수하기 위해 노력하지 않습니다. 계약의 종료를 유지하지 않으면 컴파일러에서 특정 동작 (가비지 입력, 가비지 출력)을 기대할 수 없습니다.

사람들은 나를 위해 일하더라도 휴대용이 아닌 솔루션을 좋아하지 않는 것 같습니다.

" 나를 위해 일하는 것 같다 "고 말하는 것이 더 나을 수 있습니다 . 컴파일러에서 특정 동작이 작동한다고 구체적으로 문서화하지 않으면 (즉, 표준 표준 플러스 컴파일러 문서로 구성된 풍부한 표준을 사용하지 않는 한) 실제로 작동하는지 또는 실제로 신뢰할 수 있는지 모릅니다. 많은 시스템 (그래서,에 배치에서 예를 들어, 부호있는 정수 오버 플로우 일반적으로 결과 INT_MAX+1일반적으로 INT_MIN) - 그 컴파일러 "알"을 제외하고 자주 결코 산술 정수 서명하지 않는 (올바른) C 프로그램에서 오버 플로우, 그리고 그 "이에 따라 매우 놀라운 최적화를 수행 지식".


1
로 컴파일 할 수 있고 -fwrapv부호있는 정수 산술이 항상 래핑되는 약간 다른 비표준 언어를 사용하고 있습니다.
user253751

@immibis : C89가 작성된 이론적 근거 문서에 따르면, 현대의 대다수 컴파일러는 정수 오버 플로우에 대한 자동 래핑 의미를 정의했습니다. 대부분의 경우 정수 오버플로의 경우에 발생하는 일에 대해 어떤 종류의 보증을하는 것은 그러한 보장 없이는 코드가 더 효율적일 수있게 할 수 있습니다. 래핑 동작은 부호없는 수학을 사용하여 에뮬레이션 할 수 있지만 요구 사항을 충족하기에 느슨하지만 여전히 의미론이 더 효율적인 코드를 허용 할 수 있습니다].
supercat

@immibis : 수정 주의자들이 특정 플랫폼 (또는 경우에 따라 100 % 만장일치)에 대해 컴파일러간에 거의 만장일치로 구현 된 행동이 그러한 플랫폼에서 결코 "표준"이 아니었다는 사실을 사람들에게 설득 할 수 없었습니다. 이러한 동작을 피해야함으로써 발생하는 효율성 손실은 컴파일러가이를 취소함으로써 달성 할 수있는 "최적화"에 의해 보상되지 않습니다.
supercat

4

나는 표준을 따라야한다는 것을 알고 있지만, 프로그래머의 창의성에 족쇄를 두지 않습니까? 다른 컴파일러가 표준을 따르는 방식에는 여전히 몇 가지 차이점이 있습니다. 예를 들어 성능과 속도면에서 매우 우수한 코드, 즉 중요한 모든 코드를 작성할 수 있지만 여전히 표준을 엄격하게 준수하지는 않을 수 있습니다.

아닙니다. 표준은 무엇을 할 수 있는지 알려줍니다. 지정되지 않은 경우, 귀하는 정의되지 않은 행동 영역에 있고 모든 베팅이 해제됩니다. 프로그램은 무엇이든 자유롭게 할 수 있습니다.


void main()vs의 특정 예를 언급 했으므로 int main()답변을 향상시킬 수 있습니다.

void main()기본 함수의 표준 선언이 아닙니다. 확장을 통해 일부 컴파일러에서 작동하지만 구현에 의존합니다. 그것이 작동하더라도 원하는 것을 수행하는지 확인해야합니다. 문제는 컴파일러 개발자가 void main()다음 컴파일러 릴리스에서 제거 하여 응용 프로그램을 중단하기로 결정할 수 있다는 것 입니다.

반면에, 표준은 main의 서명을 명확하게 정의하고 int main()어떻게해야하는지 알려줍니다.


한편, 표준에는 정의되어 있지 않은 것이 있습니다. 그런 다음 다른 표준 (예 : POSIX)이 적용될 수 있습니다. c ++ 03 표준 프로그램은 1 스레드이기 때문에 가장 좋은 예는 c ++ 03의 스레드 구현입니다. 이 경우 플랫폼 종속 라이브러리 또는 boost 와 같은 것을 사용해야합니다 .


4
컴파일러가 표준이 아닌 모든 것은 정의되지 않은 동작이 아니며, 컴파일러 확장은 결정적이고 신중하다는 의미에서 잘 정의되어 있습니다. UB는 그렇지 않습니다.
Daniel Gratzer

@jozefg 요청 된 방식-OP가 UB 구현 방식을 생각한 것이 분명합니다. 예를 들어 스레드는 c ++ 03에 정의되지 않았습니다.
BЈовић

1
@deworde : 댓글에서 답변이 제거되었습니다.
Kevin

@jozefg 특정 컴파일러가 항상 부호있는 정수를 래핑하는 경우 문서화되지 않은 언어 확장으로 간주 될 수 있습니다. (물론 문서화되지 않았다는 것은 확장을 제거하지 않았다는 보장이 없다는 것을 의미합니다)
user253751

-6

프로젝트가 정부 프로젝트 또는 군대 프로젝트와 같은 특수 프로젝트에 관한 것이면 규칙을 따르지 말고 분산 된 팀과 함께 오픈 소스 또는 대규모 프로젝트에 대해 이야기하는 경우 규칙을 따라야합니다.


2
설명이 없으면 다른 사람이 반대 의견을 게시 할 경우이 답변이 쓸모 없게 될 수 있습니다. 예를 들어, 누군가가 "프로젝트가 정부 프로젝트 나 군대 프로젝트 와 같은 특수 프로젝트에 관한 것이면 규칙을 따르지만 오픈 소스에 대해 이야기하는 경우 규칙을 따를 필요는 없습니다" 와 같은 클레임을 게시하는 경우 ... ,이 답변이 독자가 두 가지 반대 의견을 선택하는 데 어떻게 도움이됩니까? 더 나은 형태로 편집 하는 것을 고려하십시오
gnat

2
알다시피 : 정부 프로젝트에 얼마나 많은 표준이 있는지 알게되면 놀랄 것입니다 ...
Deer Hunter
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.