argc가 상수가 아닌 이유는 무엇입니까? # 3 주 “를 사용 CONST

int main( const int argc , const char[] const argv)

으로 효과적인 C ++ 항목 # 3 주 “를 사용 CONST 가능한”나는 “이 ‘상수’매개 변수를 만들지 왜 생각을 시작 const?”.

argc프로그램에서 의 값 이 수정 되는 시나리오가 있습니까?



답변

이 경우 역사가 요인입니다. C는 이러한 입력을 “불변”으로 정의했으며 기존 C 코드와의 호환성은 C ++의 초기 목표였습니다.

와 같은 일부 UNIX API는 getopt실제로 조작을 수행 argv[]하므로 const이러한 이유로도 만들 수 없습니다 .

(참고 : 흥미롭게도, getopt의 프로토 타입이 수정 argv[]하지는 않지만 가리키는 문자열을 수정할 수 있음을 암시 하지만, Linux man 페이지는 getopt인수 를 순열 한다고 표시하고 그들이 장난 스럽다는 것을 알고있는 것처럼 보입니다 . The man page at the Open 그룹은이 순열을 언급하지 않습니다.)

퍼팅 constargcargv많이 살 것, 그리고 같은 관행, 프로그래밍 오래된 학교를 무효화 할 것입니다 :

// print out all the arguments:
while (--argc)
    std::cout << *++argv << std::endl;

나는 그런 프로그램을 C로 작성했고 나는 혼자가 아니라는 것을 알고있다. 어딘가 에서 예제를 복사했습니다 .


답변

C 표준 (ISO / IEC 9899 : 2011)은 다음과 같이 말합니다.

5.1.2.2.1 프로그램 시작

¶1 프로그램 시작시 호출되는 함수의 이름은 main. 구현은이 함수에 대한 프로토 타입을 선언하지 않습니다. 반환 유형이 int이고 매개 변수없이 정의되어야합니다.

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

또는 두 개의 매개 변수를 사용합니다 (여기에서 argc및 로 지칭됩니다. argv이름이 선언 된 함수에 로컬이기 때문에 모든 이름을 사용할 수 있음).

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

또는 동등한 것; 10) 또는 다른 구현 정의 방식으로.

¶2 선언 된 경우 main함수에 대한 매개 변수 는 다음 제약 조건을 준수해야합니다.

  • 의 가치 argc 음수가 아니어야합니다.
  • argv[argc] 널 포인터 여야합니다.
  • 의 값 argc이 0보다 크면 배열 구성원 argv[0]
    argv[argc-1] inclusive를 은 프로그램 시작 전에 호스트 환경에서 구현 정의 값을 제공하는 문자열에 대한 포인터를 포함합니다. 그 목적은 호스팅 된 환경의 다른 곳에서 프로그램을 시작하기 전에 결정된 정보를 프로그램에 제공하는 것입니다. 호스트 환경이 대문자와 소문자로 된 문자가있는 문자열을 제공 할 수없는 경우 구현은 문자열이 소문자로 수신되는지 확인해야합니다.
  • 의 값 argc이 0보다 크면로 가리키는 문자열 argv[0]
    은 프로그램 이름 을 나타냅니다. argv[0][0]호스트 환경에서 프로그램 이름을 사용할 수없는 경우 널 문자가됩니다. 의 값 argc이 1보다 크면 argv[1]through가 가리키는 문자열 argv[argc-1]
    은 프로그램 매개 변수 를 나타냅니다.
  • 배열이 가리키는 매개 변수 argcargv및 문자열은 argv프로그램에 의해 수정 가능해야하며 프로그램 시작과 프로그램 종료 사이에 마지막으로 저장된 값을 유지해야합니다.

10) 따라서으로 int정의 된 typedef 이름으로 대체 int되거나의 유형이 argv로 작성 될 수 있습니다
char **argv.

마지막 글 머리 기호에 유의하십시오. argc및 둘 다 argv수정 가능해야 한다고 말합니다 . 수정할 필요는 없지만 수정할 수 있습니다.


답변

argcmain()이전 날짜에 대한 함수 서명 때문에 일반적으로 상수가 아닙니다 const.

argc는 스택 변수이므로 변경해도 사용자 고유의 명령 줄 처리 외에는 영향을주지 않습니다.

물론 const원하는 경우 선언 할 수 있습니다.


답변

const형식 인수 의 최상위 수준 은 함수 유형의 일부가 아닙니다. 원하는대로 추가하거나 제거 할 수 있습니다. 함수 구현에서 인수로 수행 할 수있는 작업에만 영향을줍니다.

따라서 argc자유롭게 추가 할 수 있습니다 const.

그러나 기능 서명을 변경하지 않고 argv는 문자 데이터 const를 만들 수 없습니다 . 즉, 표준 main함수 시그니처 중 하나 가 아니므로 main함수 로 인식 할 필요가 없습니다 . 그래서 좋은 생각이 아닙니다.


main장난감이 아닌 프로그램에서 표준 인수를 사용하지 않는 좋은 이유 는 Windows에서 국제 문자가있는 파일 이름과 같은 실제 프로그램 인수를 나타낼 수 없기 때문입니다. Windows에서는 Windows ANSI로 인코딩 된 매우 강력한 규칙이기 때문입니다. Windows에서는 GetCommandLineAPI 함수 측면에서 좀 더 이식 가능한 인수 액세스 기능을 구현할 수 있습니다 .


당신이 추가에서 아무것도 방지, 합산 constargc있지만, 가장 유용한 const에 -ness가 argv당신에게 표준이 아닌 줄 것입니다 main기능을, 대부분의 아마 같은 인식되지 않습니다. 다행스럽게도 (아이러니하게) 이식 가능한 심각한 코드에 대한 표준 인수를 사용하지 않는 좋은 이유가 main있습니다. 간단히 말해서, 실습에서는 영어 알파벳 문자 만있는 오래된 ASCII 만 지원합니다.


답변

의 서명은 main다소에서 역사적 유물이다 C. 역사적으로는 C하지 않았다 const.

그러나 constconst의 효과는 컴파일 시간에만 적용되므로 매개 변수를 선언 할 수 있습니다 .


답변

왜냐하면는 argc지역 변수 (그리고 C ++에서는 참조 등이 아님)이고 특별한 장소는 main이전 버전과의 호환성 헛소리가 응용 프로그램이 const로 만들 도록 강제 할 이유없이 엄청난 양의 여유를 부여한다는 것을 의미 하기 때문 입니다.

main() {}

int main() {}

main() { return 0; }

main(int argc, char* argv[]) { return 0; }

int main(const int argc, const char** argv) { /* no return*/ }

이러한 다양한 변형은 다양한 C 및 C ++ 컴파일러에서 컴파일됩니다.

따라서 궁극적으로 argc가 const가 아니라는 것은 아닙니다. 꼭 그래야 할 필요는 없지만 원하는 경우 가능합니다.

http://ideone.com/FKldHF , C 예 :

main(const int argc, const char* argv[]) { return 0; }

http://ideone.com/m1qc9c , C ++ 예제

main(const int argc) {}

답변

역사적인 이유를 제외하고 argc와 argv를 non-로 유지하는 좋은 이유 const는 컴파일러 구현이 main에 대한 인수로 무엇을 할 것인지 알지 못하기 때문입니다. 단지 해당 인수를 제공해야한다는 것을 알고 있기 때문입니다.

자체 함수 및 관련 프로토 타입을 정의 할 때 만들 수있는 매개 변수 const와 함수가 수정할 매개 변수를 알고 있습니다 .

극단적으로 생각하면 모든 함수에 대한 모든 매개 변수가 선언되어야한다고 선언 할 수 있으며 const, 변경해야 할 이유가 있다면 (예 : 배열을 검색하기 위해 인덱스를 감소) 로컬 비 const변수 를 만들어야 합니다. const인수의 값을 해당 변수에 복사하십시오 . 이는 바쁜 업무와 실질적인 이점이없는 추가 LOC를 만듭니다. 인수 값을 수정하지 않는 경우 적절한 정적 분석기가 선택되며 매개 변수를 만드는 것이 좋습니다 const.