C99에서 가장 유용한 새 기능은 무엇입니까? [닫은]


78

C99 는 10 년 이상 사용되었지만 지원이 느리게 진행되어 대부분의 개발자가 C89를 고수했습니다. 지금도 C 코드에서 C99 기능을 발견하면 가끔 약간 놀랐습니다.

이제 대부분의 주요 컴파일러가 C99를 지원하므로 (MSVC는 주목할만한 예외이며 일부 임베디드 컴파일러도 뒤처짐) C로 작업하는 개발자는 C99 기능을 사용할 수 있는지 알아야합니다. 일부 기능은 이전에 표준화 된 적이없는 일반적인 기능 ( snprintf예 :)이거나 C ++ (유연한 변수 선언 배치 또는 한 줄 //주석) 에서 익숙 하지만 일부 새로운 기능은 C99에서 처음 도입되었으며 많은 프로그래머에게 익숙하지 않습니다.

C99에서 가장 유용한 새 기능은 무엇입니까?

참고로 C99 표준 (초안으로 표시되어 있지만 내가 아는 한 업데이트 된 표준과 동일), 새로운 기능 목록GCC C99 구현 상태가 있습니다.

답변 당 하나의 기능을 사용하십시오. 여러 답변을 남겨주세요. 새로운 기능을 보여주는 짧은 코드 예제가 권장됩니다.


2
사람들 이 C99에서 싫어하는 기능에 대한 유사한 위키가 있어야합니다 !
Alok Singhal

음, 유해하거나 지원되지 않는 C99에 대한 질문이 특징이었다 stackoverflow.com/questions/1898890/...
브라이언 캠벨

감사. 링크 텍스트를 변경하여 실제 표준이 아닌 초안임을 나타내야하며 n1256에 연결하는 동안 링크해야합니다. :-). BTW, gcc.gnu.org/c99status.html을 보면 대부분의 C99가 gcc에서 지원된다고 말하지는 않습니다. 그리고 gcc는 가장 널리 사용되는 C 컴파일러 중 하나이기 때문에 ...
Alok Singhal

2
임베디드 프로세서 분야에서 C99는 여전히 잘 지원되지 않을 수 있습니다.
Craig McQueen

1
@Alok 나는 대부분의 기능을 지원하는 수준이라고 부를 것입니다. 당신이 그것을 어떻게 정의 하느냐에 달려 있다고 생각하지만 사람들이 사용하고 싶어하는 대부분의 중요한 기능이 지원되고 몇 가지 라이브러리 문제를 제쳐두고 있다고 생각합니다. @Craig Fair 충분히, 임베디드 컴파일러에 대한 면책 ​​조항을 추가했습니다.
Brian Campbell

답변:


77

나는 타이핑에 너무 익숙해

C ++에서는 C99가 아닌 컴파일러를 사용하는 것이 고통 스럽습니다.


44
게다가 항상 좋은
일인

그것은 내 선택이기도하다.
figurassa 2010 년

2
@Oliver <풍자>하지만 다음의 지침 sub esp, 4add esp, 4제거 </ 풍자>!
콜 존슨

72

stdint.h정의되는 int8_t, uint8_t등 없음은 더 정수가 얼마나 폭에 대한 비 휴대용 가정을 할 필요.


19
DE : AD : BE : EF : CA : FE 이후 최고의 16 진수 구문입니다.
Kevin L.

Decafbad는 무엇을 의미합니까?
Pacerier 2013-09-21

5
@Pacerier 예제를 설명하는 데 사용되는 임의의 16 진수 상수입니다. 그러나 유머 가치를 위해 "디카 페인이 나쁘다"라는 철자는 디카 페인 커피가 실제보다 열등하다는 것을 의미합니다.
Brian Campbell

5
좋아, 나는 그들의 유머와 관련이 없다 ...
Pacerier

66

새로운 초기화 메커니즘이 매우 중요하다고 생각합니다.

OK-설득력있는 예는 아니지만 표기법은 정확합니다. 배열의 특정 요소와 구조의 특정 멤버를 초기화 할 수 있습니다.

아마도 더 나은 예는 이것이 될 것입니다.


6
그것은 설득력있는 시연입니다. 거기에 상응하는 문자열 테이블과 함께 엄청난 양의 열거 테이블이 있습니다.
u0b34a0f6ae 2011

5
@ColeJohnson : 두 번째 예제를 자세히 살펴보면 초기화 프로그램이 순서대로 나열되지 않지만 올바르게 작동하는 것을 볼 수 있습니다. 정의만으로는 불가능합니다. 첫 번째 예제는 배열의 인덱스 4 만 초기화합니다. 정의만으로는 불가능합니다.
Jonathan Leffler 2013

2
또한 동일한 인덱스를 두 번 이상 사용하면 두 번째로 첫 번째 사용이 무시된다는 점에 유의해야합니다. 여기에서 내 질문을 참조하십시오. 예 : stackoverflow.com/questions/16742467/…
johnny

51

가변 길이 배열 :


3
VLA 어레이가 정말 훌륭하다고 생각하십니까? C11은 그것들을 선택적으로 만듭니다.
Z boson

3
(x가 마이너스 인 경우, 또는 스택 손상) 그냥 스택 오버 플로우를 방지하기 위해 입력 위생을 적용하는 것을 잊지 마세요 :if (x < 0) x = 0; else if (x > 1024) x = 1024;
앤드류 D' Addesio

51

로 시작하는 한 줄 주석 지원 //.


7
+1 내가 아는 모든 컴파일러는 이미 이것을 지원합니다. 표준에 언급 될 때입니다.
slebetman

41

블록의 시작이 아닌 다른 위치에서 변수를 선언 할 수 있습니다.


2
나는 이것에별로 관심이 없다. 내 생각에 변수는 필요할 때 범위로 가져와야 할뿐만 아니라 필요하지 않을 때 범위에서 제거해야합니다. 중간 블록 변수는 거의 항상 스코프 내에서 예상보다 오래 걸려 있습니다.
supercat 2011 년

5
@supercat 당신이 선호 int a; int b; a = f(); b = g();하는 int a = f(); int b = g();? 초기화되는 위치에 가까운 변수를 선언하는 것은 오류를 줄이기 위해 엄청납니다.
Ryan Haining

@RyanHaining : 또는 중첩 된 범위 블록을 만듭니다 ( "이 블록은 범위 지정을위한 것"이라는 표준 구문이 있었으면 좋겠습니다.이 목적을 위해 널 매크로를 쉽게 사용할 수 있지만 조금보기 흉해 보입니다.
supercat

@supercat 이에 대한 표준 구문이 있습니다. /* this block is just for scoping */ { } /* scope */:)
alx

@CacahueteFrito : if(1) /* Scoping block */ { }조금 더 낫다고 생각 하지만 더 큰 문제는 범위 지정과 제어가 직교 개념이라는 것입니다. 루프 내에서 범위를 지정하는 것이 합리적 일 때가 있지만, 루프 주위에 범위를 지정하는 것이 더 유용 할 때가 있으며, 코드가 생성에 필요한 값을 보유하기 위해 객체를 만드는 경우도 많습니다. 수명이 더 긴 개체,하지만 그 이후에는 절대로 없습니다 (예 : float dx=x2-x1, dy=y2-y1; float distance = sqrt(dx*dx+dy*dy);dx와 dy를 범위에 유지해야 할 이유가 없습니다.
supercat

36

가변 매크로. 인수의 무제한으로 상용구 코드를 더 쉽게 생성 할 수 있습니다.


34

snprintf() -진지하게, 안전한 형식의 문자열을 할 수 있다는 것은 많은 가치가 있습니다.


1
매우 사실입니다. 다른 사람이 없으면이 답변을 직접 추가하려고했습니다.
Brian Campbell

29

복합 리터럴. 멤버 별 구조 설정은 '89;)

불필요한 변수를 선언하지 않고 자동 저장 기간이있는 개체에 대한 포인터를 가져 오는 데 사용할 수도 있습니다.

의욕


4에 대한 스택에 메모리를 할당해야합니까?
AlphaGoku

29

유연한 어레이 멤버.

6.7.2.1 구조 및 공용체 지정자

특별한 경우로, 이름이 지정된 멤버가 둘 이상있는 구조의 마지막 요소에 불완전한 배열 유형이있을 수 있습니다. 이를 유연한 배열 구성원 이라고합니다 . 두 가지 예외를 제외하고 유연한 배열 구성원은 무시됩니다. 우선, 구조체의 크기는 unspeci 인터넷 ED 길이의 어레이로 배열 FL 융통성이 부재를 대체 달리 동일한 구조의 마지막 요소의 오프셋) 둘째, 동일하게한다 .(또는->) 연산자에는 유연한 배열 멤버가있는 구조 (에 대한 포인터) 인 왼쪽 피연산자가 있고 해당 멤버의 오른쪽 피연산자 이름을 지정합니다. 접근중인 객체보다 구조를 더 크게 만듭니다. 배열의 오프셋은 교체 배열의 오프셋과 다르더라도 유연한 배열 구성원의 오프셋을 유지해야합니다. 이 배열에 요소가 없으면 하나의 요소가있는 것처럼 동작하지만 해당 요소에 액세스하거나 그 요소를 지나서 포인터를 생성하려는 시도가 있으면 동작이 정의되지 않습니다.

예:


2
마침내이 코셔를 만드는 데 +1. 내가 본 모든 TCP / IP 소켓 코드에 있습니다.
slebetman

사실, buf [1]을 사용하고 malloc 크기에서 1을 빼는 일반적인 트릭보다 훨씬 더 정결하다고 생각합니다. 트릭은 일반적 일 수 있지만 컴파일러에서 생성 된 인덱싱 코드가 buf []의 인식 된 크기에 따라 달라질 수 있으므로 정의되지 않은 동작으로 간주합니다 (적절하게 buf [MAX_SIZE]를 사용하고 malloc 크기에서 MAX_SIZE를 뺍니다).
supercat 2011 년

25

부울 유형입니다.

이제 다음과 같이 할 수 있습니다.

인쇄됩니다


2
이것을 생각하는 사람은 누구나 순전히
천재적입니다

아니요, boolC99에서는 변수에 할당 된 값이 항상 1 또는 0이되도록 강제합니다. 이것이 C99 컴파일러와 "시뮬레이션 된" bool유형 의 이전 컴파일러에서 실행되는 코드가있는 경우주의해야하는 이유 입니다. 사용 !!하면 휴대용으로 만들 수 있습니다. v = !!5;동일한 의미를 갖지만 읽을 수 없습니다.
Patrick Schlüter 2014

6과 같은 짝수를 할당하면 1이 인쇄됩니까?
phuclv

예. 모든 비 제로 값은 1로 대체 될 줘야
패트릭 Schlüter

18

inline기능 지원 .


실제로 GCC는 인라인 할 함수를 결정할 때 일반적으로 인라인 키워드를 무시하고, 달리 강제하지 않는 한 자체 휴리스틱을 기반으로 자동으로 인라인합니다.
daf

7
daf : inline그래도 도움이됩니다. 두 개 이상의 번역 단위에서 함수를 정의 할 수 있기 때문입니다. 헤더 파일에 넣어서 모듈 간 인라인 기회를 제공 할 수 있습니다.
caf

@dafinline __attribute__((force_inline))
Cole Johnson

18

이미 언급 된 복합 리터럴이지만 여기에 내 매력적인 예가 있습니다.

데이터가 힙에있는 경우에도 데이터를 초기화하는 명확한 방법입니다. 0으로 초기화하는 것을 잊을 방법이 없습니다.



15

유니 코드 이스케이프 시퀀스 지원 :

또는 리터럴 유니 코드 문자 :

(참고 : 로케일에 따라 작동하지 않을 수 있습니다. 다른 인코딩에 대한 이식 가능 지원은 이보다 더 많은 작업이 필요합니다.)


12

16 진 부동 소수점 상수 ( 0x1.8p0f) 및 변환 지정자 ( %a, %A). 낮은 수준의 숫자 세부 정보를 자주 처리하는 경우 십진수 리터럴 및 변환에 비해 크게 향상되었습니다.

알고리즘에 상수를 지정할 때 반올림에 대한 걱정을 덜어 주며 저수준 부동 소수점 코드를 디버깅하는 데 매우 유용합니다.


3
네, 다른 Stack Overflow 질문에서 부동 소수점 숫자가 어떻게 작동하는지 누군가에게 설명하려고 할 때 방금 이것을 사용했습니다.
Brian Campbell

9

개인적으로 저는 IEC 60559 : 1989 (마이크로 프로세서 시스템의 이진 부동 소수점 산술)에 대한 승인 과 훨씬 더 나은 부동 소수점 지원을 좋아합니다.

비슷한 맥락에서, 부동 소수점 반올림 모드를 설정하고 쿼리하고 Nan / Infinity / 비정규 숫자 등을 확인하는 것이 좋습니다.


음, MS는이 일을 좋아하지 않는다
콜 존슨

C는 반올림 모드의 개념에 적합하지 않습니다. 부동 소수점 수학은 부작용이있는 것으로 처리되어야하기 때문입니다. 무언가를 갖는 것은 "희망 -에 대한 - 더 - 최고"부동 소수점 의미는 유용하지만, 나는 많은 구현은 정말 모든 부록 F.의 요구 사항을 존중할지 모르겠 더 나은보다
supercat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.