C ++에서 C 헤더를 사용할 때 std :: 또는 전역 네임 스페이스의 함수를 사용해야합니까?


113

C는 정확히는 아니지만 C ++의 하위 집합입니다. 따라서 우리는 이름을 약간 변경하여 C ++에서 대부분의 C 함수 / 헤더를 사용할 수 있습니다 ( stdio.hto cstdio, stdlib.hto cstdlib).

제 질문은 실제로 일종의 의미 론적입니다. C ++ 코드에서, 내가 호출 할 수 있습니다 (GCC 컴파일러의 최신 버전을 사용) printf("Hello world!");std::printf("Hello world!");와 정확히 동일하게 작동합니다. 그리고 참조에서 나는 그것을 사용하고 있습니다 std::printf("Hello world!");.

내 질문은 std::printf();C ++에서 사용하는 것이 선호 됩니까? 차이가 있습니까?


17
언젠가 그들이 C글로벌 네임 스페이스 에 라이브러리 심볼을 덤핑하는 것이 불법이라고 명령하는 경우 나는 std::qualified 버전을 사용하는 것을 선호합니다 . (또한 나는 그들이 그것을 불법으로 만들었 으면 좋겠다).
Galik 2015 년

3
@Galik : 동의합니다. 그것은 C ++ 컴파일러를 사용하는 C 문제에 대한 많은 어리석은 질문을 안전하게 할 것입니다.
이 사이트에 대한 너무 정직

7
"조금 임신"은 없습니다. C는 서브 세트이거나 그렇지 않습니다. 사실은 그렇지 않습니다 . 이것이 C ++에서 작동하도록 C 헤더를 수정해야하는 이유입니다.
이 사이트에 대한 너무 정직

2
"거의 전부"는 셀 수없는 많은 요소에 대해 이야기 할 때 매우 쓸모없는 척도입니다. 같은 주장으로 아마도 C와 Java를 관련시킬 수있을 것입니다.
Daniel Jour

9
@sasauke 아니, 하위 집합이 아닙니다. C와 C ++는 확실히 하위 집합을 공유 하지만 C 자체 C ++의 하위 집합 이 아닙니다 .
상자성 크로아상

답변:


106

C ++ 11 표준에서 (강조 내) :

D.5 C 표준 라이브러리 헤더 [depr.c.headers]

  1. C 표준 라이브러리와의 호환성을 위해 ...
  2. 각각 name.h 형식의 이름을 가진 모든 C 헤더 는 해당 cname 헤더에 의해 표준 라이브러리 네임 스페이스에 배치 된 각 이름 이 전역 네임 스페이스 범위 내에 배치되는 것처럼 작동 합니다. 인 이 이름은 제 선언 또는 공간 범위 내에서 정의되어 있는지 불특정 (3.3.6) 네임 스페이스 STD 하고 명시하여 선언 - (7.3.3)가 글로벌 네임 스페이스의 영역에 주입된다.
  3. 예 : 헤더 는 네임 스페이스 내에서 선언 및 정의를 <cstdlib> 확실히 제공 합니다 std . 또한 전역 네임 스페이스 내에서 이러한 이름을 제공 할 수 있습니다. 헤더 는 C 표준에서와 마찬가지로 전역 네임 스페이스 내 에서 동일한 선언과 정의를 <stdlib.h> 확실히 제공합니다 . 네임 스페이스 내에서 이러한 이름을 제공 할 수도 있습니다 .std

«name.h»헤더 사용은 더 이상 사용되지 않으며 향후 개정에서 제거 할 후보로 식별되었습니다.

따라서«cname»헤더를 포함하고 std네임 스페이스 의 선언과 정의를 사용하는 것이 좋습니다 .

어떤 이유로«name.h»헤더를 사용해야하는 경우 (사용되지 않음, 위 참조) 전역 네임 스페이스의 선언 및 정의를 사용하는 것이 좋습니다.

즉, 선호

#include <cstdio>

int main() {
    std::printf("Hello world\n");
}

위에

#include <stdio.h>

int main() {
    printf("Hello world\n");
}

1
N3242는 C ++ 표준이 아닙니다. N3337 C ++ 11과의 차이점이 가장 적은 초안입니다.
MM

3
또한 Jonathan Wakely의 <cstdlib>가 Red hat 블로그에서 생각하는 것보다 더 복잡한 이유를 참조하십시오 . 그는 C ++ 표준 라이브러리 구현 자의 관점에서 여러 문제를 자세히 설명합니다. 그는 또한 C ++ 98로 거슬러 올라가는 역사를 제공합니다.
jww

@sergej-주제에 대한 C ++ 03 처리를 알고 계십니까? 아니면 무슨 일이 일어날 지 맞거나 놓치나요?
jww

5
<name.h>는 더 이상 사용되지 않을 수 있으며 조만간 제거 될 가능성은 없습니다. 사실 정반대입니다. 더 이상 사용되지 않는 라벨을 제거하라는 제안이 있습니다 ( open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0619r0.html#3.5 참조) . "마지막으로 C 헤더는 C 및 POSIX와의 중요한 호환성 레이어로서 본질적으로 영원히 유지 될 것임이 분명해 보입니다. 헤더를 폐기 취소 할 가치가있을 수 있습니다. [..]"
Sjoerd

82

<cmeow>항상 제공 ::std::purr하거나 제공하지 않을 수도 있습니다 ::purr.

<meow.h>항상 제공 ::purr하거나 제공하지 않을 수도 있습니다 ::std::purr.

포함하는 헤더에서 제공하는 것이 보장되는 양식을 사용하십시오.


7
불쌍한 변장의 STL?
nwp 2015-09-17

@nwp 아니. (15 자)
TC

@TC 불행히도 컴파일러에서 시도했지만 전 처리기 오류 <cmeow><meow.h>제공하지도 ::std::purr않고 ::purr오히려 제공하지도 않습니다 . 만 <cstdio>및 / 또는 <stdio.h>제공 ::std::printf및 / 또는 ::printf. : P
LF

4
@LF strcat생성 해야 할 수도 있습니다 ::purr.
Lundin

8

아니, 당신은 어느 쪽이든 괜찮습니다.

원래 목적은이었다 <___.h>헤더 글로벌 네임 스페이스에 모든 것을 넣어 C 버전이 될 것하고 <c___>는 ified 버전의의 장소 다 - 헤더가 C ++ 것 std네임 스페이스.

실제로, 그래도 C ++ 버전은 또한 글로벌 네임 스페이스에 모든 것을 넣어. 그리고 std::버전 을 사용하는 것이 "올바른 일" 이라는 명확한 합의가 없습니다 .

따라서 기본적으로 원하는 것을 사용하십시오. 가장 일반적인 방법은 전역 네임 스페이스 ( printf대신 std::printf) 에서 C 표준 라이브러리 함수를 사용하는 것입니다 .하지만 하나를 "더 나은"것으로 간주 할 이유가별로 없습니다.


2
"그리고 std :: 버전을 사용하는 것이"올바른 일 "이라는 명확한 합의가 없습니다." 어, 네, 그게 옳은 일이라는 합의가 절대적으로 있습니다.
Miles Rout

4
합의에 도달했는지 여부를 객관적으로 어떻게 결정합니까?
Jeremy Friesner 2015 년

9
@JeremyFriesner에 대해 게시하고 동의하지 않는 의견이 있는지 확인하십시오. :)
jalf

1
@JeremyFriesner : 표준은 C ++ 헤더 버전이 전역 네임 스페이스에 식별자를 넣는 것을 보장하지 않습니다. 표준은 또한 C 헤더 버전을 더 이상 사용하지 않습니다. 그것은 나에게 꽤 합의 된 것 같습니다. ;-)
DevSolar 2015 년

2
@DevSolar는 사전에서 "consensus"라는 단어를 찾습니다. 표준이 말하는 것이 아니라 C ++ 프로그래머가 말하는 것, 특히 그들이하는 일에 관한 것 입니다. 거기의 이유는 말 그대로 모든 표준 라이브러리 구현은 C 헤더를 제공하는이, 그리고 ++ 헤더뿐만 아니라 글로벌 네임 스페이스에 모든 것을 넣어 C가 있습니다. :)
jalf 2015 년

3

유일한 차이점은 범위 확인을 std::printf()추가 std::하면 나중에 같은 이름의 함수를 작성하는 사람으로부터 자신을 보호 할 수 있다는 것입니다. 이로 인해 네임 스페이스 충돌이 발생합니다. 두 가지 사용 모두 정확히 동일한 OS API 호출로 이어질 것입니다 (Linux에서 실행하여 확인할 수 있음 strace your_program).

printf()가장 일반적으로 사용되는 함수 중 하나 인 것처럼 누군가가 이와 같은 함수의 이름을 지정할 가능성은 매우 낮 습니다. 또한 C ++에서 iostreams는 cstdioprintf와 같은 함수에 대한 호출보다 우선합니다.


1
반대로 printf강력한 타이핑이 없기 때문에 C ++에서 심하게 손상 될 가능성이 높습니다. 더 나은 버전으로 교체하는 것은 매우 자연스러운 일입니다.
Konrad Rudolph

1
@KonradRudolph 원하는 경우 그렇게 찾을 수 있지만 틀릴 것입니다. 강력한 타이핑을 의미하는 것이 아니며 필요한 강력한 타이핑으로 쉽게 해결할 수없는 문제가 많습니다. 그렇기 때문에 비교 가능한 많은 C ++ 솔루션이 printf보다 훨씬 느립니다. "더 나은"버전으로 바꾸고 싶다면 언어와 프로그래머 사이의 계약을 깨뜨리고 처음부터 죄의 상태에있는 것입니다.
Alice

1
@Alice 음, 내가 어떤 계약을 위반하지 있어요 : std::printf다른 mynamespace::printf명시 적으로 나 이름이 함수 내부에서 그 그림자 내 자신의 함수를 정의 할 수 있고, C ++ std. 그것은 논쟁의 여지가 없습니다. printf느슨한 타이핑으로 인해 효율적인 주장에 관해서도 물론 잘못되었습니다. printf특히 효율적이지 않고 강력한 형식의 더 효율적인 구현이 많이 있습니다.
Konrad Rudolph

@KonradRudolph 절대적으로 잘못되었습니다. 당신은 표준에 쓰여진 계약을 깨고 있는데, 어떤 수량 자도없는 printf는 C 구조에 분명하게 적용됩니다. 전역 네임 스페이스의 별칭을 지정하는 네임 스페이스 사용은 좋은 생각이 아닙니다. 그것은 논쟁의 여지가 없습니다 .
Alice

5
@Alice 이것에 대한 표준을 인용 해 주시겠습니까? 나는 그런 말을 알지 못합니다.
Konrad Rudolph

3

C ++ 11 표준에서 :

각각 name.h 형식의 이름을 가진 모든 C 헤더는 해당 cname 헤더에 의해 표준 라이브러리 네임 스페이스에 배치 된 각 이름이 전역 네임 스페이스 범위 내에 배치되는 것처럼 작동합니다. 이러한 이름이 std 네임 스페이스의 네임 스페이스 범위 (3.3.6) 내에서 처음 선언되거나 정의 된 다음 명시 적 using-declarations (7.3.3)에 의해 전역 네임 스페이스 범위에 삽입되는지 여부는 지정되지 않습니다.

따라서을 사용 <cstdio>하면, 즉 글로벌 네임 스페이스가 아니라에 printf있을 것임을 확신 할 수 있습니다 namespace std.
전역 네임 스페이스를 사용하면 이름 충돌이 발생합니다. 이것은 C ++ 방식이 아닙니다.

따라서 <cstdio>헤더를 사용 하고 있으며 그렇게하도록 조언합니다.


4
이런 식으로 작동하기를 원하지만 이것은 사실이 아닙니다. 포함 <cstdio>하면 std :: printf가 존재한다는 것을 보장하지만 :: printf도 존재 하거나 존재하지 않을 경우 표준에서 보장 하지 않습니다. 사실, 내가의 :: printf와 들었어요 모든 컴파일러 입니다 당신이 포함되면 전역 네임 스페이스에 주입 <cstdio>.
wjl

3

내 자신의 연습에서 : std::접두사를 사용하십시오 . 그렇지 않으면 부동 소수점을 사용하는 경우 언젠가 abs 매우 고통스럽게 물릴 것입니다.

정규화되지 않음 은 일부 플랫폼에 abs정의 된 기능을 나타냅니다 int. 다른 사람들에게는 과부하가 걸립니다. 그러나 std::abs항상 모든 유형에 대해 오버로드됩니다.


2

printf없이 사용하면 std::일부 이름 충돌이 발생할 수 있으며 많은 C ++ 개발자가 나쁜 습관으로 간주합니다. Google은이 문제에 대해 친구이지만 여기에 몇 가지 링크가 있습니다. 도움이되기를 바랍니다.

"namespace std 사용"이 나쁜 습관으로 간주되는 이유는 무엇입니까? http://www.cplusplus.com/forum/beginner/61121/


4
using namespace std나쁜 습관이지만 한정자 printf없이 사용하는 std::것은 아닙니다.
syntagma 2015 년

using namespace std;여기서 내 문제가 아닙니다. 나는 그것을 사용하지 않습니다. printf();그리고 std::printf();C ++에서 작업하지 않고 using namespace std;그것이 내가 질문을 게시 한 이유입니다.
DeiDei 2015 년

@REACHUS 동의하지 않습니다. 두 시나리오 사이에는 차이가 없습니다.
Konrad Rudolph

나는 std::printf그것을 사용하지 않을 것 입니다.
trenki

@KonradRudolph 나는 차이가 있다고 말하지 않고 내 의견을 표현했습니다 (더 많은 근거는 내 답변 참조).
syntagma 2015 년

2

stdio에서

이것은 표준 C 라이브러리 헤더 @c stdio.h의 C ++ 버전이며, 그 내용은 (대부분) 해당 헤더와 동일하지만 네임 스페이스 @c std에 포함됩니다 (매크로로 정의 된 이름 제외). 씨).

따라서 아무런 차이가 없어야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.