정의되지 않은 C ++ 동작이 C 정의 된 동작을 충족하면 어떻게됩니까?


10

*.cppC 컴파일러가 아닌 C ++로 컴파일 하는 파일이 있습니다. 포함 함수는 C (정확한 경우 수정하십시오!)로 정의 된 것처럼 보이는 캐스트 (마지막 줄 참조)에 의존하지만이 특수 유형의 C ++에서는 그렇지 않습니다.

[...] C++ code [...]

struct sockaddr_in sa = {0};
int sockfd = ...;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
bind(sockfd, (struct sockaddr *)&sa, sizeof sa);

[...] C++ code [...]

이것을 C ++ 파일로 컴파일하기 때문에 이것이 현재 정의되었거나 정의되지 않은 동작입니까? 아니면 *.c파일을 파일 로 옮겨서 동작을 정의해야합니까?


1
파일 확장자는 의미가 없습니다. C 또는 C ++로 컴파일하는 경우에만 가능합니다.
Fredrik

1
해당 유형은 서로 상속되지 않으며 관계가 없으며 C ++에서 정의되지 않습니다.
Daniel Stephens

1
일반적으로 파일의 .c확장자 가 있으면 C 컴파일러가 자동으로 호출됩니다.
Igor R.

1
나는 C ++ 코드에서 항상 그 트릭을 수행합니다. 왜 그것이 당신에게 효과가 없을지 모르겠습니다. 어딘가에 헤더가 없습니까?
user4581301

3
@DanielStephens이 프로그램은 포인터를 역 참조하려고하지 않습니다. 캐스트 자체는 때때로 참조 만 가능합니다. C면이 포인터를 실제 유형으로 올바르게 캐스트하면 모든 것이 정상입니다. 이러한 유형의 정렬 요구 사항이 다른 경우 주조 문제가 발생할 수 있습니다.
user7860670

답변:


6

이것은 C ++과 C 모두에 정의되어 있습니다. 결과 포인터를 역 참조하지 않기 때문에 엄격한 앨리어싱 규정을 위반하지 않습니다.

다음 은 이것을 허용하는 C ++ (@interjay 및 @VTT 덕분) 의 인용문입니다 .

객체 포인터는 다른 유형의 객체 포인터로 명시 적으로 변환 될 수 있습니다.

이것을 가능하게하는 C (감사 @StoryTeller) 의 인용문은 다음과 같습니다 .

객체 유형에 대한 포인터는 다른 객체 유형에 대한 포인터로 변환 될 수 있습니다.

이것들은 하나의 포인터 타입이 다른 포인터 타입으로 변환 될 수 있고 (선택적으로 다시 변환 될 수 있음) 지정합니다.

POSIX인용문은 다음과 같습니다.

를 sockaddr_in 구조는 인터넷 주소 패밀리의 주소를 저장하는 데 사용됩니다. 이 유형에 대한 포인터는 소켓 함수와 함께 사용하기 위해 sockaddr * 를 구성하는 응용 프로그램에 의해 캐스트됩니다 .

이 함수 ( bind)는 C 표준 라이브러리의 일부이므로 내부에서 진행되는 (특히 형식 캐스팅 포인터 역 참조) 작업에는 정의되지 않은 동작이 없습니다.


보다 일반적인 질문에 대답하려면 :

C와 C ++는 서로 다른 두 언어입니다. C ++에서는 정의되지 않았지만 C ++에서는 정의되지 않았지만 C ++에서는 정의되지 않았습니다. 두 언어 사이의 묵시적 호환성으로 인해 변경되지 않습니다. C에서는 잘 정의되어 있지만 C ++에서는 정의되지 않은 코드를 사용하려면 해당 코드를 컴파일하기 위해 C 컴파일러를 사용해야합니다.


1
@interjay 표준의 인용문으로 백업 할 수 있습니까 (C 또는 C ++ 중 어느 것이 좋습니까)?
SS Anne


1
@StoryTeller 감사합니다. 대신 HTTP 버전을 추가했습니다.
SS Anne

2
아마도 이것은 POSIX 표준의 결함입니다. 두 번째 주장 bind은 a이어야 const void *하지만 C 언어의 존재 (및 C ++의 존재) bind보다 먼저 시작 void됩니다. 그들은 어느 시점에을 추가하기 위해 업데이트 const했지만 기본 유형을 수정하지 않았습니다.
Chris Dodd

1
강의를 추천 해드릴 수 있습니다. youtube.com/watch?v=_qzMpk-22cc 그래도 답이 유효한지, 아니면 실제로 반대인지를 확신 할 수 있는지 잘 모르겠습니다. -o C ++가 악몽입니다 .. lol
Daniel Stephens

-3

C와 C ++ 코드 사이의 호출은 모두 해당 표준의 관점에서 정의되지 않은 동작을 호출하지만 대부분의 플랫폼은 그러한 것을 지정합니다.

C 또는 C ++ 표준의 일부와 구현 문서가 함께 동작을 정의 또는 설명하지만 다른 부분이이를 정의되지 않은 것으로 특성화하는 경우, 구현은 고객의 요구에 가장 잘 맞는 방식으로 코드를 처리 할 수 ​​있습니다. 어떤 패션이든 고객의 요구에 무관심합니다. 표준이 관할권 밖에서 이러한 문제를 고려한다는 사실은 다양한 목적에 대한 적합성을 주장하는 구현이이를 어떻게 의미있게 처리해야하는지에 대한 판단을 의미하지는 않지만 일부 컴파일러 관리자는 그러한 신화에 동의합니다.


첫 번째 단락 : "C와 C ++ 코드 사이의 호출은 모두 정의되지 않은 동작을 호출합니다. " "정의되지 않은 동작 호출"(없는) 호출이 있어도 여전히 의미가 없습니다.
궤도에서 가벼움 경주

두 번째 단락 : 당신이 무슨 말을하는지 모르겠다.
궤도에서 가벼움 경주

@LightnessRacesinOrbit이 답변은 [language-lawyer] 태그를 질문에 추가 한 결과라고 생각합니다. 나는 이제 그것을 더 잘 생각하고 (답은 너무 문자적인 경향이 있음) 그것을 제거했다.
SS Anne

1
@ JL2210 당신의 잘못이라고 생각하지 않습니다.
궤도에서 가벼움 경주
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.