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
수정 가능해야 한다고 말합니다 . 수정할 필요는 없지만 수정할 수 있습니다.
답변
argc
main()
이전 날짜에 대한 함수 서명 때문에 일반적으로 상수가 아닙니다 const
.
argc는 스택 변수이므로 변경해도 사용자 고유의 명령 줄 처리 외에는 영향을주지 않습니다.
물론 const
원하는 경우 선언 할 수 있습니다.
답변
const
형식 인수 의 최상위 수준 은 함수 유형의 일부가 아닙니다. 원하는대로 추가하거나 제거 할 수 있습니다. 함수 구현에서 인수로 수행 할 수있는 작업에만 영향을줍니다.
따라서 argc
자유롭게 추가 할 수 있습니다 const
.
그러나 기능 서명을 변경하지 않고 argv
는 문자 데이터 const
를 만들 수 없습니다 . 즉, 표준 main
함수 시그니처 중 하나 가 아니므로 main
함수 로 인식 할 필요가 없습니다 . 그래서 좋은 생각이 아닙니다.
main
장난감이 아닌 프로그램에서 표준 인수를 사용하지 않는 좋은 이유 는 Windows에서 국제 문자가있는 파일 이름과 같은 실제 프로그램 인수를 나타낼 수 없기 때문입니다. Windows에서는 Windows ANSI로 인코딩 된 매우 강력한 규칙이기 때문입니다. Windows에서는 GetCommandLine
API 함수 측면에서 좀 더 이식 가능한 인수 액세스 기능을 구현할 수 있습니다 .
당신이 추가에서 아무것도 방지, 합산 const
에 argc
있지만, 가장 유용한 const
에 -ness가 argv
당신에게 표준이 아닌 줄 것입니다 main
기능을, 대부분의 아마 같은 인식되지 않습니다. 다행스럽게도 (아이러니하게) 이식 가능한 심각한 코드에 대한 표준 인수를 사용하지 않는 좋은 이유가 main
있습니다. 간단히 말해서, 실습에서는 영어 알파벳 문자 만있는 오래된 ASCII 만 지원합니다.
답변
의 서명은 main
다소에서 역사적 유물이다 C
. 역사적으로는 C
하지 않았다 const
.
그러나 const
const의 효과는 컴파일 시간에만 적용되므로 매개 변수를 선언 할 수 있습니다 .
답변
왜냐하면는 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
.