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 그룹은이 순열을 언급하지 않습니다.)
퍼팅 const에 argc와 argv많이 살 것, 그리고 같은 관행, 프로그래밍 오래된 학교를 무효화 할 것입니다 :
// 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]
은 프로그램 매개 변수 를 나타냅니다.- 배열이 가리키는 매개 변수
argc및argv및 문자열은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 함수 측면에서 좀 더 이식 가능한 인수 액세스 기능을 구현할 수 있습니다 .
당신이 추가에서 아무것도 방지, 합산 const에 argc있지만, 가장 유용한 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.