문제

그만큼 C 표준 (5.1.2.2.1 프로그램 시작) 말한다 :

프로그램 스타트 업에서 호출 된 함수의 이름은 Main입니다. [...]
리턴 유형의 int와 매개 변수가없는 것으로 정의되어야합니다.
int main(void) { /* ... */ }

또는 두 개의 매개 변수가 있습니다 [...] :
int main(int argc, char *argv[]) { /* ... */ }

그리고 나중에 말한다 :

ARGC의 가치는 음이 없어야한다.

  • 그렇지 않아야합니다 argc 로 정의됩니다 unsigned int, argc 아마도 '인수 수'를 의미합니까?
  • 해야 한다 argc 인덱스로 사용됩니다 argv?

그래서 나는 C 표준이 배열 색인 유형에 대해 무언가를 말하는지 궁금해하기 시작했습니다. 서명 되었습니까?

6.5.2.1 배열 첨자:

표현 중 하나는 유형이 있어야합니다.객체 유형에 대한 포인터``, 다른 표현에는 있어야합니다 정수 유형결과에는 유형이 있습니다.유형’’.

그것은 그 서명에 대해 아무 말도하지 않습니다 (또는 나는 그것을 찾지 못했습니다). 네거티브 배열 인덱스를 사용하여 코드를 보는 것이 일반적입니다.array[-1])하지만 정의되지 않은 행동이 아닙니까?

  • Array의 인덱스가 서명되지 않아야합니까?
도움이 되었습니까?

해결책

Main ()의 int의 이유는 역사적입니다. 언어가 표준화되기 오래 전에 항상 그런 식으로 사용되었습니다. 배열 인덱스의 요구 사항은 배열의 한계 (또는 어떤 상황에서는 끝을 지나서) 내에 있다는 것입니다. 다른 모든 것은 정의되지 않으므로 서명은 중요하지 않습니다.

다른 팁

1) Main () Argc 유형 : IMHO 표준은 매우 오래된 전통을 계속하고 있습니다 (30 년 이상!). 또는 CPU는 "argc"가 "부호없는"정의되면 불만을 제기하지 않지만 표준을 벗어났습니다!)

2) 대부분의 구현에서 Argv [argc]는 합법적이며 NULL로 평가합니다. 실제로, 인수 목록의 끝을 찾는 대체 방법은 Argv [i]가 무일하게 시간이 끝날 때 0에서 Argv를 반복하는 것입니다.

3) 음수 인 배열/포인터 산술은 (pn)에서 p까지의 주소 범위가 동일한 메모리 객체에 속하는 한 합법적입니다. 즉, 당신은 가질 수 있습니다

char array[100];
char *p;

p = &array[50];
p += -30; /* Now p points to array[20]. */

이 포인터 산술 사용은 그 결과 포인터가 원래 메모리 객체 ( "배열") 내부에 머무르기 때문에 합법적입니다. 대부분의 시스템에서 포인터 산술은이 규칙을 위반하여 메모리를 탐색하는 데 사용할 수 있지만, 이는 완전히 시스템 의존적이기 때문에 휴대용이 아닙니다.

일반적으로 C에서 "최소한의 놀라움의 원칙"은 서명되지 않은 정당한 이유가 없다면 변수를 서명하는 것이 바람직하다는 것을 암시합니다. 서명 및 서명되지 않은 값을 혼합 할 때 유형 프로모션 규칙이 예상치 못한 결과로 이어질 수 있기 때문입니다. argc 서명되지 않은이 간단한 비교는 놀라운 결과로 이어질 것입니다.

if (argc > -1)

(그만큼 -1 홍보됩니다 unsigned int, 따라서 그 값은 변환됩니다 UINT_MAX, 그것은 거의 확실히 더 큽니다 argc).

1) argc는 논쟁의 수이지만, 정직하게 말하면, 프로그램 이름 앞에 논쟁을 어떻게 준비 할 수 있습니까? argv[0]. 프로그램을 상상해보십시오 foo, 당신은 단순히 말할 수 없습니다 args1 foo args2 그것은 의미가 없지만 argc 서명 된 유형입니다 int, 즉, 그런 것은 없습니다 argv[-1] 당신을 'Args1'... ...

2) ARGC가 실제로 인수 벡터에 대한 색인이 아닙니다 (따라서 'Argv') 런타임이 실행 파일 프로그램 이름을 제로 오프셋으로 사용합니다. argv[0] 따라서 argc 1이 꺼집니다.

3) 포인터 조작 측면에서 배열 인덱스, 제공 당신은 배열 첨자가 포인터의 바로 가기이기 때문에 배열 첨자를 사용하는 메모리 블록의 경계 내에 있습니다.

char v[100];
char *p = &v[0];

You can do this:

p[55] = 'a'; 

Which is the same as

*(p + 55) = 'a';

You can even do this:

p = &v[55];

p[-10] = 'b' /* This will stuff 'b' into 45'th offset! */

Which is the same as

*(p - 10) = 'b';

또한 경계를 벗어난 방식으로 배열을 사용하고 조작하는 경우 - 정의되지 않은 동작이며 처리 방법, 아마도 세분화 결함 또는 프로그램 충돌에 대한 런타임 구현에 따라 다릅니다. ..

4) *닉스 환경에서 일부는 메인에 세 번째 매개 변수가 제공됩니다. char **endvp, 다시 이것은 DOS/Windows의 Microsoft World에서 거의 사용되지 않습니다. 일부 *NIX 런타임 구현은 사전 역사적 이유로 런타임을 통해 환경 변수를 통과 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top