int argc, char * argv []은 무슨 뜻인가요?


508

많은 C ++ IDE와 컴파일러에서 주요 함수를 생성 할 때 다음과 같이 보입니다.

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

명령 줄 컴파일러를 사용하여 IDE없이 C ++을 코딩 할 때 다음과 같이 입력합니다.

int main()

매개 변수없이 이것이 무엇을 의미하며 내 프로그램에 중요합니까?


47
프로그램이 명령 행 인수를 무시할 경우 작성하는 것이 좋습니다. 프로그램이 명령 행 인수를 처리해야하는 경우 IDE가 올바르게 수행합니다.
Jonathan Leffler

30
해커를위한 힌트 : int main(int argc, char* argv[], char* envp[])마지막 인수를 선언 하고 인쇄 해보십시오 . ;)
ulidtko

7
@ulidtko 초보자들이 그들의 프로그램에 취약점을 도입하도록 가르치는 것은 좋지 않습니다;)
Gab 是 好人

13
@Gab 환경 변수의 간단한 인쇄는 어떻게 취약점을 야기합니까? 오염 된 문자열을 그대로 system()호출, DB 쿼리 등에 전달하지 마십시오 . 사용자 입력과 마찬가지로.
ulidtko

2
@ulidtko Interesting .. char **envp인수 를 사용하는 동안 오염 된 문자열, db 쿼리 등을 전달할 필요가없는 이유를 설명 할 수 있습니까 ?
마스터 제임스

답변:


651

argvargc명령 줄 인수를 전달하는 방법입니다 main()C와 C ++에서.

argc에 의해 지정된 문자열 수입니다 argv. 실제로 모든 구현은 프로그램 이름을 배열 앞에 추가하므로 실제로는 1에 인수의 수를 더한 값이됩니다.

변수 이름은 argc( argument count ) 및 argv( argument vector )로 명명 되지만 유효한 식별자를 부여 할 수 있습니다 int main(int num_args, char** arg_strings). 똑같이 유효합니다.

int main()명령 행 인수를 처리하지 않으려는 경우에는 완전히 생략하여을 생성 할 수도 있습니다 .

다음 프로그램을 시도하십시오 :

#include <iostream>

int main(int argc, char** argv) {
    std::cout << "Have " << argc << " arguments:" << std::endl;
    for (int i = 0; i < argc; ++i) {
        std::cout << argv[i] << std::endl;
    }
}

로 실행 ./test a1 b2 c3하면 출력

Have 4 arguments:
./test
a1
b2
c3

8
argc0 일 argv수 있으며이 경우 NULL 일 수 있습니다. 표준 AFAIK에서 허용합니다. 실제로이 작업을 수행하는 시스템에 대해 들어 본 적이 없지만 확실히 존재할 수 있으며 표준을 위반하지 않을 것입니다.

77
@Chuck : "값은 argv[argc]0이어야합니다"(C ++ 03 §3.6.1 / 2)이므로 argvnull 일 수 없습니다.
James McNellis

20
@Chuck : C (적어도 C99)는 동일한 요구 사항이 있습니다.
James McNellis

2
내가 추가해야한다고 생각했지만, 이것은 대부분의 시스템에서 동일하지만 때로는 추상화되어 있습니다. 예를 들어, Pascal / Delphi / Lazarus에서는 다음과 같은 이점이 있습니다. ParamStr 및 ParamCount (메모리가 올바르게 제공되는 경우). 내 요점은, 당신이 (언제든지) 다른 언어 / 오세로 네이티브 응용 프로그램을 작성할 때, 위의 내용을 사용할 수있는 좋은 기회가 있으며, 지원하는 모든 시스템에서 완벽하게 동일한 (카운트 / 문자열 목록) 작동한다는 것입니다 그들.
Christian

8
@ EmilVikström 아니요, 심각한 오류로 인해 segfault가 발생했을 수 있습니다. *NULL확실히 같지 않습니다 NULL.
meagar

52

argc명령 행에서 프로그램으로 전달되는 인수 수이며 인수 argv배열입니다.

다음과 같이 인수 수를 알고있는 인수를 반복 할 수 있습니다.

for(int i = 0; i < argc; i++)
{
    // argv[i] is the argument at index i
}

19

sh구문을 사용하여 프로그램을 실행한다고 가정하십시오 .

myprog arg1 arg2 'arg 3'

메인을로 선언하면 int main(int argc, char *argv[])(대부분의 환경에서) 다음 main()과 같이 호출됩니다.

p = { "myprog", "arg1", "arg2", "arg 3", NULL };
exit(main(4, p));

그러나 메인을로 선언하면 int main()다음과 같이 호출됩니다.

exit(main());

그리고 당신은 인수가 전달되지 않습니다.

두 가지 추가 사항 :

  1. 이것들은 두 가지 표준 필수 서명입니다. main . 특정 플랫폼이 추가 인수 또는 다른 리턴 유형을 허용하는 경우 이는 확장이며 이식 가능한 프로그램에 의존해서는 안됩니다.
  2. *argv[]그리고 **argv당신이 쓸 수 있도록 정확히 동일 int main(int argc, char *argv[])int main(int argc, char **argv).

2
기술적 인 경우 구현에서 두 개의 사전 정의 된 버전을 제공하는 경우 구현 basic.start.main/2정의 된 추가 버전을 명시 적으로 허용 main()합니다. 따라서 그것들은 정확히 부적합 하지 않습니다 . 가장 일반적인 것은 envpC와 C ++에서 매우 잘 알려져 있기 때문에 문자 그대로 C 표준의 J.5 (공통 확장) 섹션에서 첫 번째 항목입니다 .
저스틴 타임-복원 모니카

1
멋진 pedantry @Justin에 감사드립니다. 더 정확한 답변을 업데이트했습니다.
Toby Speight

모름- 재현 할 수있는 최소한의 예제 를 작성하여 요청 하는 것이 좋습니다 (프로세스가 스스로 대답하는 데 충분하지 않다고 가정).
Toby Speight

9

main프로그램 시작시 제공된 명령 행 매개 변수를 나타내는 매개 변수입니다. argc매개 변수는 명령 줄 인수의 수를 나타내고, char *argv[]커맨드 라인 상에 제공된 각각의 인수를 나타내는 문자열 (문자 포인터) 배열이다.


2
Argv []에는 항상 argv [arg]가 널 포인터로 있습니다. Argv [0]은 항상

3
@ user3629249 : 반드시 그런 것은 아닙니다. argv[0]하여 프로그램 실행 C 프로그램과 같이 준대로입니다 argv[0]. Bash의 경우 종종 실행 파일의 경로 이름이지만 항상 Bash가 다른 프로그램을 실행하는 유일한 프로그램은 아닙니다. 편심이지만 다음을 사용하는 것은 허용 char *args[] = { "cat", "/dev/null", "/etc/passwd", 0 }; execv("/bin/ls", args);됩니다. 많은 시스템에서 프로그램에 의해 볼 가치는 argv[0]있을 것입니다 cat실행이 경우에도 /bin/ls.
Jonathan Leffler

7

main함수는 두 개의 매개 변수를 가지고 있습니다 argcargv. argc정수 ( int) 매개 변수이며 프로그램에 전달 된 인수의 수입니다.

프로그램 이름은 항상 첫 번째 인수이므로 프로그램에 대한 인수는 하나 이상 있으며 최소값 argc은 1입니다. 그러나 프로그램 자체에 두 개의 인수가있는 경우 값은 argc3입니다.

매개 변수 argv는 문자열 배열을 가리키며 인수 벡터 라고합니다 . 함수 인수로 구성된 1 차원 문자열 배열입니다.


5
int main();

이것은 간단한 선언입니다. 명령 행 인수를 사용할 수 없습니다.

int main(int argc, char* argv[]);

이 선언은 프로그램이 명령 행 인수를 가져와야 할 때 사용됩니다. 다음과 같이 실행할 때 :

myprogram arg1 arg2 arg3

argc, 또는 인수 개수는 4 (4 개의 인수)로 설정되고 argv인수 벡터는 "myprogram", "arg1", "arg2"및 "arg3"에 대한 문자열 포인터로 채워집니다. 프로그램 호출 ( myprogram)이 인수에 포함됩니다!

또는 다음을 사용할 수 있습니다.

int main(int argc, char** argv);

이것도 유효합니다.

추가 할 수있는 다른 매개 변수가 있습니다.

int main (int argc, char *argv[], char *envp[])

envp매개 변수에는 환경 변수도 포함됩니다. 각 항목은 다음 형식을 따릅니다.

VARIABLENAME=VariableValue

이처럼 :

SHELL=/bin/bash    

환경 변수 목록은 null로 종료됩니다.

중요 : 모든 사용하지 마십시오 argv또는 envp호출에 값을 직접 system()! 이것은 거대한악의적 인 사용자가 환경 변수를 명령 줄 명령으로 설정하고 (잠재적으로) 막대한 피해를 입힐 수 있기 때문에 보안 허점입니다. 일반적으로을 사용하지 마십시오 system(). 거의 항상 C 라이브러리를 통해 더 나은 솔루션이 구현됩니다.


3

첫 번째 매개 변수는 제공된 인수 수이고 두 번째 매개 변수는 해당 인수를 나타내는 문자열 목록입니다.


7
argv [0]의 첫 번째 항목은 인수가 아닌 프로그램 이름입니다.
user3629249

@ user3629249 프로그램 경로가있는 프로그램 이름. ;)
마스터 제임스

1

둘다

int main(int argc, char *argv[]);
int main();

C 또는 C ++ 프로그램의 진입 점에 대한 법적 정의입니다. Stroustrup : C ++ 스타일 및 기술 FAQ 에는 기본 기능에 대해 가능하거나 합법적 인 일부 변형이 자세히 설명되어 있습니다.


4
호환성과 가독성 을 위해 void int main()= ... = ...를 넣기를 원할 수 int main(void)있습니다. C의 모든 이전 버전에서 void 함수가 선언에서 빈 매개 변수 목록을 가질 수 있는지 여부는 알 수 없습니다.
dylnmc

1
@dylnmc 이것은 가독성을 높이 지 않으며 모든 C ++ 버전에서 정확히 동일합니다. C에서만 이것은 차이가 있지만 정의에서는 선언이 아닙니다.
Ruslan

@Ruslan 죄송합니다. 방금 C를 배우는 동안 이것을 게시했으며 C의 초기 버전에서는 C void가 필요 하다는 것을 읽었을 것입니다 . 저를 인용하지 마십시오. 나는 그것이 약간 어리석은 의견이라는 것을 알고 있습니다. 그래도 아프지 않습니다.
dylnmc

argc <3이 오류를 반환하면 어떻게됩니까? 무엇이 잘못되었을 수 있습니까?
AVI
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.