Programming

'C'에서 색인이 0으로 시작되는 이유는 무엇입니까?

procodes 2020. 6. 15. 22:33
반응형

'C'에서 색인이 0으로 시작되는 이유는 무엇입니까?


왜 배열의 색인 생성이 1이 아닌 C에서 0으로 시작합니까?


C에서, 배열의 이름은 본질적으로 포인터, 메모리 위치에 대한 참조이므로, 배열 array [n]은 시작 요소에서 떨어진 메모리 위치 n- 요소를 나타냅니다. 이는 인덱스가 오프셋으로 사용됨을 의미합니다. 배열의 첫 번째 요소는 배열이 참조하는 메모리 위치 (0 개의 요소)에 정확히 포함되므로 array [0]으로 표시해야합니다.

더 많은 정보를 위해서:

http://developeronline.blogspot.com/2008/04/why-array-index-should-start-from-0.html


이 질문은 1 년 전에 게시되었지만 여기에갑니다 ...


위의 이유에 대해

하지만 다 익스트라의 기사 (이전에 지금은 삭제에서 참조 대답은 ) 수학적 관점에서 의미가 있습니다, 그것은 관련으로하지 않습니다 이 프로그램에 올 때.

언어 사양 및 컴파일러 디자이너가 내린 결정은 컴퓨터 시스템 디자이너가 0부터 카운트를 시작하기로 한 결정을 기반으로합니다.


가능한 이유

대니 코헨 (Danny Cohen)의 평화대한 간청 에서 인용 .

모든 b의 경우, 첫 번째 b ^ N 음이 아닌 정수는 번호가 0에서 시작하는 경우에만 정확히 N 자리 (앞의 0 포함)로 표시됩니다.

이것은 매우 쉽게 테스트 할 수 있습니다. base-2에서 2^3 = 88 번째 숫자는 다음과 같습니다.

  • 1부터 카운트를 시작하면 8 (바이너리 : 1000)
  • 0부터 카운트를 시작하면 7 (바이너리 : 111)

1113비트 를 사용하여 표현할 수 있지만 1000추가 비트 (4 비트)가 필요합니다.


이것이 왜 관련이 있습니까?

컴퓨터 메모리 주소에는 비트 단위의 2^N이 있습니다 N. 이제 1부터 계산을 시작하면 2^N셀에 N+1주소 줄 이 필요 합니다. 정확히 하나의 주소에 액세스하려면 추가 비트가 필요합니다. ( 1000위의 경우). 이를 해결하는 또 다른 방법은 마지막 주소에 액세스 할 수 없게하고 N주소 행을 사용하는 것 입니다.

둘 다 최적의N 주소 라인을 사용하여 모든 주소에 액세스 할 수있는 시작 카운트 0에 비해 차선책입니다 .


결론

에서 시작하기로 결정한 0이후에는 실행중인 소프트웨어를 포함한 모든 디지털 시스템에 코드가 침투 하여 기본 시스템이 해석 할 수있는 코드로 코드를 변환하는 것이 더 간단 해졌습니다. 그렇지 않은 경우 머신과 프로그래머 사이에 모든 어레이 액세스에 대해 하나의 불필요한 변환 조작이 있습니다. 컴파일이 쉬워집니다.


논문에서 인용 :

여기에 이미지 설명을 입력하십시오


왜냐하면 0은 배열의 포인터에서 배열의 첫 번째 요소까지의 거리입니다.

치다:

int foo[5] = {1,2,3,4,5};

0에 액세스하려면 다음을 수행하십시오.

foo[0] 

그러나 foo는 포인터로 분해되며 위의 액세스는 포인터에 액세스하는 유사한 포인터 산술 방법을 갖습니다.

*(foo + 0)

요즘 포인터 산술은 자주 사용되지 않습니다. 그러나 되돌아 가면 주소를 가져 와서 X "ints"를 시작점에서 멀어지게하는 편리한 방법이었습니다. 물론 현재 위치를 유지하려면 0을 추가하면됩니다!


0 기반 인덱스가 허용하기 때문에 ...

array[index]

...로 구현하려면 ...

*(array + index)

인덱스가 1 기반 인 경우 컴파일러는 다음을 생성해야합니다. *(array + index - 1)이 "-1"은 성능을 저하시킵니다.


컴파일러와 링커를 더 단순하게 만들었 기 때문에 (쓰기가 더 쉬워졌습니다).

참고 :

"... 주소와 오프셋으로 메모리를 참조하는 것은 거의 모든 컴퓨터 아키텍처의 하드웨어에서 직접 표현되므로 C의이 디자인 세부 사항으로 인해 컴파일이 더 쉬워집니다"

"... 이것은 더 간단한 구현을 만듭니다 ..."


배열 인덱스는 항상 0으로 시작합니다. 기본 주소가 2000이라고 가정합니다 arr[i] = *(arr+i). 이제이 if i= 0의미 *(2000+0는 배열에서 첫 번째 요소의 기본 주소 또는 주소와 같습니다. 이 인덱스는 오프셋으로 취급되므로 deaault 인덱스는 0부터 시작합니다.


같은 이유로 수요일이고 누군가가 수요일까지 며칠을 물으면 1이 아니라 0이라고 말하고 수요일이 며칠 동안 목요일까지 며칠을 물으면 2가 아니라 1을 말합니다.


0에서 시작하는 번호 매기기에 대해 읽은 가장 우아한 설명은 값이 숫자 줄의 표시된 위치가 아니라 그 사이의 공백에 저장된다는 관찰입니다. 첫 번째 항목은 0과 1 사이에 저장되고 다음 항목은 1과 2 사이에 저장됩니다. N 번째 항목은 N-1과 N 사이에 저장됩니다. 항목의 범위는 양쪽의 숫자를 사용하여 설명 할 수 있습니다. 개별 항목은 일반적으로 아래의 숫자를 사용하여 설명됩니다. 범위 (X, Y)가 주어지면 아래 숫자를 사용하여 개별 숫자를 식별하면 산술을 사용하지 않고 첫 번째 항목을 식별 할 수 있지만 (항목 X) 마지막 항목을 식별하려면 Y에서 하나를 빼야합니다 (Y -1). 위의 번호를 사용하여 항목을 식별하면 범위의 마지막 항목을 쉽게 식별 할 수 있습니다 (항목 Y 임).

위의 숫자를 기준으로 항목을 식별하는 것은 끔찍하지는 않지만 범위 (X, Y)의 첫 번째 항목을 X 위의 항목으로 정의하면 일반적으로 아래 항목으로 정의하는 것보다 더 잘 작동합니다 (X + 1).


기술적 이유는 배열의 메모리 위치에 대한 포인터가 배열의 첫 번째 요소의 내용이라는 사실에서 비롯 될 수 있습니다. 1의 색인으로 포인터를 선언하면 프로그램은 일반적으로 원하는 값이 아닌 내용에 액세스하기 위해 1의 값을 포인터에 추가합니다.


1 기반 행렬에서 X, Y 좌표를 사용하여 픽셀 화면에 액세스하십시오. 공식은 완전히 복잡합니다. 왜 복잡한가? X, Y 좌표를 오프셋 인 하나의 숫자로 변환하게됩니다. 왜 X, Y를 오프셋으로 변환해야합니까? 그것이 메모리가 연속적인 메모리 셀 스트림으로 컴퓨터 내부에서 구성되는 방식이기 때문입니다. 컴퓨터가 배열 셀을 처리하는 방법 오프셋 사용 (제로 기반 인덱싱 모델 인 첫 번째 셀로부터의 변위).

따라서 코드의 어느 시점에서 1 기반 수식을 0 기반 수식으로 변환하는 데 필요한 (또는 컴파일러가 필요) 컴퓨터가 메모리를 처리하는 방식이기 때문입니다.


크기가 5 인 배열을 생성하려고한다고 가정합니다.
int array [5] = [2,3,5,9,8]

배열의 첫 번째 요소가 위치 100을 가리키고

인덱싱이 1이 아닌 1에서 시작한다고 가정합시다. 0.

이제 정수의 크기가 4 비트 이므로 인덱스의 도움으로 첫 번째 요소의 위치를 ​​찾아야합니다
(1 번째 요소의 위치는 100임을 기억하십시오) 따라서 인덱스 1을 고려하면 위치는 크기가됩니다 of index (1) * integer (4) = 4 크기 이므로 실제 위치는 100 + 4 = 104입니다.







이것은 초기 위치가 100에 있었기 때문에 사실이 아닙니다.
104
아닌 100을 가리켜 야합니다 . 이것은

이제 0에서 인덱싱을 취한
다음
첫 번째 요소의 위치
는 index (0) * integer의 크기 여야합니다 (4) = 0

따라서->
첫 번째 요소의 위치는 100 + 0 = 100

이며 이는 요소의 실제 위치이므로
색인이 0에서 시작하는 이유입니다.

나는 그것이 당신의 요점을 분명히하기를 바랍니다.


저는 Java 배경을 가지고 있습니다. 나는 아래의 다이어그램에서이 질문에 대한 답을 제시했다.

주요 단계 :

  1. 참조 작성
  2. 배열의 인스턴스화
  3. 배열에 데이터 할당

  • 배열이 방금 인스턴스화되었을 때에도주의하십시오 .. 값을 할당 할 때까지 기본적으로 모든 블록에 0이 할당됩니다.
  • 첫 번째 주소가 참조를 가리 키므로 배열은 0으로 시작합니다 (그림의 i : e-X102 + 0).

여기에 이미지 설명을 입력하십시오

참고 : 이미지에 표시된 블록은 메모리 표현입니다


"배열 이름 자체에 배열의 첫 번째 요소 주소가 포함되어 있기 때문에"배열은 내부적으로 포인터로 간주된다는 것을 알아야합니다.

ex. int arr[2] = {5,4};

배열이 주소 100에서 시작한다고 가정하면 요소 첫 번째 요소는 주소 100에 있고 두 번째는 104에 있습니다. 배열 색인이 1에서 시작하면

arr[1]:-

이것은 포인터 식에서 다음과 같이 쓸 수 있습니다.

 arr[1] = *(arr + 1 * (size of single element of array));

int의 크기가 4 바이트라고 생각하십시오.

arr[1] = *(arr + 1 * (4) );
arr[1] = *(arr + 4);

아시다시피 배열 이름에는 첫 번째 요소의 주소가 포함되므로 arr = 100입니다.

arr[1] = *(100 + 4);
arr[1] = *(104);

그것은,

arr[1] = 4;

because of this expression we are unable to access the element at address 100 which is official first element,

now consider array index starts from 0, so

arr[0]:-

this will be resolved as

arr[0] = *(arr + 0 + (size of type of array));
arr[0] = *(arr + 0 * 4);
arr[0] = *(arr + 0);
arr[0] = *(arr);

now, we know that array name contains the address of its first element so,

arr[0] = *(100);

which gives correct result

arr[0] = 5;

therefore array index always starts from 0 in c.

reference: all details are written in book "The C programming language by brian kerninghan and dennis ritchie"


Array name is a constant pointer pointing to the base address.When you use arr[i] the compiler manipulates it as *(arr+i).Since int range is -128 to 127,the compiler thinks that -128 to -1 are negative numbers and 0 to 128 are positive numbers.So array index always starts with zero.

참고URL : https://stackoverflow.com/questions/7320686/why-does-the-indexing-start-with-zero-in-c

반응형