programing

'in main;'이 유효한 C/C++ 프로그램인가?

prostudy 2022. 5. 8. 22:02
반응형

'in main;'이 유효한 C/C++ 프로그램인가?

내 컴파일러가 그렇게 생각하는 것 같아서 물어보는 거야.

echo 'int main;' | cc -x c - -Wall
echo 'int main;' | c++ -x c++ - -Wall

캉은 이에 대해 경고나 오류를 발생시키지 않으며 gcc는 온순한 경고만 발생시킨다.'main' is usually a function [-Wmain], 그러나 C로 컴파일되었을 때만. -std=상관없는 것 같아

그렇지 않으면, 그것은 잘 조합되고 연결된다. 종지부를 SIGBUS(나를 위해)

C와 C++에서 무엇을 반환해야 하는가?에서 (우수) 대답을 읽고 언어 사양을 통해 간단히 설명하면 분명 주요 기능이 필요한 것처럼 보일 것이다.하지만 gcc의 말벌은-Wmain('main'은 보통 기능이다) (그리고 여기서 오류가 부족함)은 아마도 다른 것을 시사하는 것 같다.

하지만 왜?이것을 위해 이상한 에지 케이스나 "역사적인" 용도가 있는가?뭐가 좋은지 아는 사람?

내 요점은 이게 호스트 환경에서 오류가 되어야 한다고 생각한다는 거지, 응?

질문이 C와 C++로 이중 태깅되기 때문에 C++와 C에 대한 추론은 다를 것이다.

  • C++는 이름 맹글링을 사용하여 링커가 텍스트로 다른 유형(예: 전역 변수)의 동일한 기호를 구별할 수 있도록 돕는다.xyz그리고 독립된 글로벌 기능xyz(int)그러나 그 이름은main결코 망가지지 않는다.
  • C는 망링을 사용하지 않기 때문에 프로그램이 다른 기호 대신 한 종류의 기호를 제공함으로써 링커를 혼동할 수 있고, 프로그램이 성공적으로 연결되도록 할 수 있다.

그게 바로 여기서 일어나고 있는 일이다: 링커는 기호를 찾기를 기대한다.main, 그리고 그것은 그렇다.그 기호가 마치 함수인 것처럼 '원한다'는 것은, 그 기호가 더 잘 알지 못하기 때문이다.제어 권한을 전달하는 런타임 라이브러리의 부분main링커에게 부탁하다main, 그래서 링커는 그것을 상징한다.main연결 단계를 완료하십시오.물론 이 작업은 런타임에 실패하며,main함수가 아니야

동일한 문제에 대한 또 다른 예는 다음과 같다.

x.c 파일:

#include <stdio.h>
int foo(); // <<== main() expects this
int main(){
    printf("%p\n", (void*)&foo);
    return 0;
}

파일 y.c:

int foo; // <<== external definition supplies a symbol of a wrong kind

컴파일:

gcc x.c y.c

이 컴파일은, 아마도 실행될 것이지만, 컴파일러에게 약속된 기호의 유형이 링커에 제공된 실제 기호와 다르기 때문에, 정의되지 않은 행동이다.

경고에 따르면, 나는 타당하다고 생각한다: C는 당신이 없는 도서관을 지을 수 있게 해준다.main그래서 컴파일러는 그 이름을 자유롭게 한다.main변수를 정의해야 하는 경우 다른 용도로 사용main알 수 없는 이유로

main예약어가 아닌 사전 정의된 식별자(예:cinendlnpos...)라는 변수를 선언할 수 있도록main 그 를 출력한다

물론:

  • 경고는 오류가 발생하기 쉬우므로 유용하다.
  • 다음이 없어도 소스 파일을 가질 수 있다.main()기능을 하다

편집

일부 참조:

  • main예약된 단어가 아님(C++11):

    그 은 할 수 없다.main프로그램 내에서 사용해서는 안 된다.다음 중 연결(3.5)main구현 정의됨.기본을 삭제된 것으로 정의하거나 기본을 삭제된 것으로 선언하는 프로그램inlinestatic또는constexpr모양이 나쁘다그 이름은 달리 예약되어 있지 않다. [예: 멤버 함수, 클래스 및 열거형을 다른 네임스페이스에 있는 엔티티처럼 , 라고 부를 수 있다. — 종료 예제 ]

    C++11 - [basic.start.main] 3.6.1.3

    [2.11/3] [...] 일부 식별자는 C++ 구현 및 표준 라이브러리(17.6.4.3.2)에 사용할 수 있도록 예약되어 있으므로 달리 사용할 수 없으며, 진단이 필요하지 않다.

    [17.6.4.3.2/1] 특정 이름 및 함수 서명의 집합은 항상 구현을 위해 유보된다.

    • 이중 밑줄 __을 포함하거나 밑줄로 시작하는 각 이름 뒤에 대문자(2.12)를 붙이는 이름은 어떤 용도로도 구현을 위해 유보된다.
    • 밑줄로 시작하는 각 이름은 글로벌 네임스페이스에서 이름으로 사용하기 위해 구현에 예약된다.
  • 프로그래밍 언어의 예약된 단어.

    예약된 단어는 프로그래머에 의해 재정의되지 않을 수 있지만, 사전 정의된 단어는 종종 어떤 용량에서 재정의될 수 있다.의 경우는 이렇다.main이 그 식별자를 사용한 선언이 그 의미를 재정의하는 범위가 있다.

이다int main;유효한 C/C++ 프로그램?

C/C++ 프로그램이 무엇인지 완전히 명확하지는 않다.

이다int main;유효한 C 프로그램?

그렇다. 자유로운 구현은 그러한 프로그램을 받아들이는 것이 허용된다.main자유로운 환경에서 특별한 의미를 가질 필요는 없다.

호스트 환경에서는 유효하지 않다.

이다int main;유효한 C++ 프로그램?

저도 그렇게 생각해요.

왜 추락하는 거지?

그 프로그램은 당신의 환경에서 이치에 맞을 필요가 없다.자유로운 환경에서 프로그램 시작과 종료, 그리고 의 의미main는 구현에 정의되어 있다.

컴파일러는 왜 나에게 경고를 하는가?

컴파일러는 프로그램이 준수되는 것을 거부하지 않는 한, 무엇이든지 당신에게 경고할 수 있다.반면에, 경고는 부적합한 프로그램을 진단하는 데 필요한 모든 것이다.이 번역 단위는 유효한 호스트 프로그램의 일부가 될 수 없으므로, 진단 메시지는 정당화된다.

이다gcc자유로운 환경인가, 아니면 호스트 환경인가?

gcc문서화하다-ffreestanding편찬 깃추가하면 경고가 사라진다.커널이나 펌웨어를 만들 때 사용할 수 있다.

g++그런 깃발은 기록하지 않는다.그것을 공급하는 것은 이 프로그램에는 아무런 효과가 없는 것 같다.g++가 제공하는 환경을 호스트한다고 가정해도 무방할 것이다.이 경우 진단 부재는 버그다.

그것은 기술적으로 허용되지 않기 때문에 경고다.시동 코드는 "메인"의 기호 위치를 사용하고 세 가지 표준 인수(argc, argv, envp)로 점프한다.그것은 그렇지 않고, 링크 시간에는 그것이 실제로 함수인지, 심지어 그러한 주장을 가지고 있는지 확인할 수 없다.이것은 또한 int main(int argc, char **argv)이 작동하는 이유이기도 하다 - 컴파일러는 envp 논쟁에 대해 알지 못하고 우연히 사용하지 않게 되어 호출자 정리일 뿐이다.

농담으로, 너는 이런 것을 할 수 있다.

int main = 0xCBCBCBCB;

x86 기계에서 그리고 경고와 비슷한 것들을 무시한 채, 그것은 컴파일뿐만 아니라 실제로도 작동할 것이다.

누군가는 이와 유사한 기술을 사용하여 여러 아키텍처에서 직접 실행되는 실행 파일(들)을 작성했다. http://phrack.org/issues/57/17.html#article.그것은 또한 IOCCC - http://www.ioccc.org/1984/mullender/mullender.c 에서 우승하는데 사용되었다.

유효한 프로그램인가?

아니요.

실행 가능한 부분이 없어 프로그램이 아니다.

컴파일하는 것이 유효한가?

유효한 프로그램과 함께 사용할 수 있는가?

컴파일된 모든 코드가 유효하기 위해 실행 가능해야 하는 것은 아니다.예를 들어 정적 및 동적 라이브러리를 들 수 있다.

오브젝트 파일을 효과적으로 작성하셨습니다.유효한 실행 파일은 아니지만 다른 프로그램이 개체에 연결할 수 있음main파일을 런타임에 로드하여 결과 파일에 저장하십시오.

이것이 오류여야 하는가?

전통적으로 C++는 사용자가 유효한 용도가 없는 것처럼 보이지만 언어의 구문에 맞는 것을 할 수 있도록 한다.

내 말은, 확실히, 이것은 오류로 재분류될 수 있지만, 왜 그럴까?경고가 하지 않는 목적은 무엇인가?

이 기능이 실제 코드에 사용될 수 있는 이론적 가능성이 있는 한, 이른바 비기능 물체를 갖는 것은 매우 가능성이 낮다.main언어에 따라 오류가 발생할 수 있다.

나는 실제 언어 기준을 인용하여 이미 주어진 답을 덧붙이고 싶다.

'in main;'이 유효한 C 프로그램인가?

요약 답변(나의 의견): 구현 시 "실행 환경 무료화"를 사용하는 경우에만 해당됨.

C11의 다음 인용문 모두

5. 환경

구현은 두 개의 데이터프로세싱 시스템 환경에서 C 소스 파일을 변환하고 C 프로그램을 실행하는데, 이를 변환 환경과 실행 환경이라고 한다[...]

5.1.2 실행 환경

프리스탠딩과 호스팅의 두 가지 실행 환경을 정의한다.두 경우 모두 실행 환경에서 지정된 C 함수가 호출될 때 프로그램 시작이 발생한다.

5.1.2.1 프리스탠딩 환경

프리스탠딩 환경(운영체계의 어떠한 이익도 없이 C 프로그램 실행이 이루어질 수 있는 환경)에서 프로그램 스타트업에 호출되는 기능의 명칭과 종류는 구현 정의된다.

5.1.2.2 호스트 환경

호스트 환경을 제공할 필요는 없지만, 존재하는 경우 다음 규격을 준수해야 한다.

5.1.2.2.1 프로그램 시작

프로그램 시작 시 호출되는 함수의 명칭은 (main)이다. [...] 매개변수가 없는 반환형 int [...] 또는 두 개의 매개변수 [...] 또는 등가 또는 다른 구현 정의 방식으로 정의해야 한다.

이로부터 다음과 같은 것이 관찰된다.

  • C11 프로그램은 무료 또는 호스트 실행 환경을 가질 수 있으며 유효하다.
  • 만약 그것이 자유분방한 기능을 가지고 있다면, 주 기능은 존재할 필요가 없다.
  • 그렇지 않으면, 반드시 활자가 돌아오는 장식이 있는 장식이 있어야 한다.

자유로운 실행 환경에서는 5.1.2에 필요한 기능이 없기 때문에 스타트업을 허용하지 않는 유효한 프로그램이라고 주장하고 싶다.호스트 실행 환경에서, 당신의 코드는 main이라는 이름을 가진 객체를 도입하지만, 반환 값을 제공할 수 없기 때문에, 만약 프로그램이 실행되도록 되어 있지 않다면, 이전에 주장할 수도 있지만, 이러한 의미에서 그것은 유효한 프로그램이 아니라고 주장할 것이다.그렇게 하는 게 어때?

'int main;'이 유효한 C++ 프로그램인가?

요약 답변(나의 의견): 구현 시 "실행 환경 무료화"를 사용하는 경우에만 해당됨.

C++14에서 인용

3.6.1 주 기능

프로그램은 프로그램의 지정된 시작인 main이라는 글로벌 기능을 포함해야 한다.주기능을 정의하기 위해 프리스트랜딩 환경의 프로그램이 필요한지는 구현에 의해 정의된다. [...] 반환형 타입 int를 가져야 하지만, 그렇지 않으면 구현 정의된다. [...] 주명은 달리 유보되어 있지 않다.

여기서, C11 표준과는 반대로, 스타트업의 기능이 전혀 언급되지 않기 때문에 자유계약 실행 환경에는 제한이 덜 적용되는 반면, 호스트 실행 환경의 경우는 C11과 거의 동일하다.

다시 한번 말하지만, 나는 당신의 코드가 유효한 C++14 프로그램이 아니라고 주장하지만, 나는 그것이 무료 사례를 위한 것이라고 확신한다.

은 실행 환경만 생각하기 때문에 번역 환경에서 이름 망링이 먼저 일어나기 때문에 dasblinkenlicht의 대답이 작용한다고 생각한다.여기서, 나는 위의 인용문이 그렇게 엄격하게 지켜지는지 잘 모르겠다.

내 요점은 이게 호스트 환경에서 오류가 되어야 한다고 생각한다는 거지, 응?

그 실수는 네 것이다.이름이 지정된 함수를 지정하지 않았음main은 ...을한다.을 반환하는.int그리고 당신의 프로그램을 호스트 환경에서 사용하려고 시도했다.

명명된 전역 변수를 정의하는 컴파일 단위가 있다고 가정해 보십시오.main프로그램을 구성하는 것은 자유 환경에서의 구현에 맡겨지기 때문에 자유 환경에서는 합법적일 수 있다.

명명된 전역 함수를 정의하는 다른 컴파일 단위가 있다고 가정해 보십시오.main은 ...을한다.을 반환하는.int그리고 논쟁은 하지 않는다.이것이 바로 호스트 환경의 프로그램이 필요로 하는 것이다.

자유 계약 환경에서 첫 번째 컴파일 유닛만 사용하고 두 번째 컴파일 유닛은 호스트 환경에서만 사용한다면 모든 것이 괜찮아.두 가지를 모두 한 프로그램에서 사용하면 어떻게 될까?C++에서는 하나의 정의 규칙을 위반하셨습니다.그것은 정의되지 않은 행동이다.C에서 단일 기호에 대한 모든 참조가 일관성이 있어야 한다는 규칙을 위반하셨습니다. 그렇지 않으면 정의되지 않은 동작입니다.정의되지 않은 행동은 구현의 개발자들에게 "감옥에서 자유롭게 나가라"는 카드다.정의되지 않은 행동에 대응하여 구현하는 것은 표준에 부합한다.구현은 정의되지 않은 행동을 탐지하기는커녕 경고할 필요도 없다.

그 편찬 단위들 중 하나만 사용했는데 잘못 사용한 것(그것이 당신이 한 짓이다)이라면?C에서는 상황이 명확하다.함수를 정의하지 못함main호스트 환경에서 두 가지 표준 양식 중 하나는 정의되지 않은 행동이다.정의하지 않았다고 가정합시다.main조도는 이 아무 도 하지 된다컴파일러/링커는 이 오류에 대해 아무 말도 하지 않아도 된다.그들이 불평하는 것은 그들을 대신해서 친절하다.C 프로그램이 오류 없이 컴파일러를 편집하고 연결한 것은 컴파일러의 잘못이 아니라 너의 잘못이다.

함수를 정의하지 못했기 때문에 C++에서는 약간 명확하지 않다.main호스트 환경에서 정의되지 않은 행동보다는 오류(즉, 진단되어야 함)이다.그러나, C++의 한 정의 규칙은 링크커가 다소 멍청할 수 있다는 것을 의미한다.링커의 일은 외부 참조를 해결하는 것이고, 하나의 정의 규칙 덕분에 링커는 그 기호들이 무엇을 의미하는지 알 필요가 없다.이름이 지정된 기호를 제공했음main, 링커는 이름이 지정된 기호를 볼 것으로 예상함main연결자에 관한 한 모든 것이 좋다.

지금까지 C에게 그것은 구현 정의 동작이다.

ISO/IEC9899에 따르면 다음과 같다.

5.1.2.2.1 프로그램 시작

1 프로그램 시작 시 호출되는 함수의 이름을 main으로 한다.구현은 이 기능에 대한 프로토타입을 선언하지 않는다.다음 매개변수가 없는 int의 반환 형식으로 정의해야 한다.

int main(void) { /* ... */ }

또는 두 개의 매개변수를 사용하여(여기서는 argc 및 argv로 표시되지만, 어떤 명칭도 사용할 수 있지만, 그것들이 선언된 함수에 로컬인 경우).

int main(int argc, char *argv[]) { /* ... */ }

또는 동등한, 또는 다른 구현 정의 방식으로.

아니, 이건 유효한 프로그램이 아니야.

C++의 경우, 이는 최근 결함 보고서 1886: main()에 대한 언어 연결에 의해 명백히 잘못된 형태로 만들어졌다.

메인()에게 명시적인 언어 연계를 제공하는 데 어떤 제약도 있는 것 같지는 않지만, 그것은 아마도 잘못된 형식이거나 조건부로 지원되어야 할 것이다.

결의안에는 다음과 같은 변경사항이 포함되었다.

글로벌 범위에서 변수 메인을 선언하거나 (모든 네임스페이스에서) C 언어 링크와 함께 메인 이름을 선언하는 프로그램이 잘못 형성되어 있다.

우리는 C++1z 초안인 최신 C++ 표준 N4527에서 이 표현을 찾을 수 있다.

clang과 gcc의 최신 버전은 이제 이를 오류로 만든다(실시간 참조).

error: main cannot be declared as global variable
int main;
^

이 결함 보고서 이전에는 진단이 필요 없는 정의되지 않은 동작이었습니다.반면에 잘못된 형식의 코드는 진단이 필요하며 컴파일러는 이를 경고 또는 오류로 만들 수 있다.

참조URL: https://stackoverflow.com/questions/27777071/is-int-main-a-valid-c-c-program

반응형