programing

2D 배열을 매개 변수로 전달할 때 열 크기를 지정해야 하는 이유는 무엇입니까?

lastcode 2023. 7. 6. 22:16
반응형

2D 배열을 매개 변수로 전달할 때 열 크기를 지정해야 하는 이유는 무엇입니까?

매개 변수가 다음과 같을 수 없는 이유

void example(int Array[][]){ /*statements*/}

배열의 열 크기를 지정해야 하는 이유는 무엇입니까?예를 들면, 3.

void example(int Array[][3]){/*statements*/}

교수님이 필수라고 하셨는데, 학교가 시작하기 전에 코딩을 하고 있었는데 이것을 매개변수로 만들었을 때 구문적이거나 의미적인 오류가 없었다는 것을 기억했습니다.아니면 제가 뭔가를 놓쳤나요?

매개 변수를 설명할 때 배열은 항상 첫 번째 요소에 대한 포인터로 쇠퇴합니다.

이 같과이선언배로 된 배열을 할 때int Array[3]void foo(int array[])그것은 배열의 시작으로 향하는 포인터로 붕괴합니다. int *Array;참고로, 다음과 같이 매개변수를 설명할 수 있습니다.int array[3]또는int array[6]아니 심지어는int *array이 모든 것들은 동등할 것이고 당신은 모든 정수 배열을 문제없이 통과할 수 있습니다.

어레이 어레이(2D 어레이)의 경우 첫 번째 요소에 대한 포인터로도 감쇠합니다. 즉, 단일 차원 어레이가 됩니다.int (*Array)[3].

여기서 크기를 지정하는 것은 중요합니다.필수가 , 을 다루는 알 수 입니다.Array[2][1]를 들면 를들면예면.

가 메모리의을 계산해야 한다는 하지 않기 위해 (파일러가연메속컴블모필위록해기항해요하제참것조을한오목다프는계야산해된에한의셋을서리▁to▁we▁()int Array[2][3]연속된 정수 블록)이며, 포인터에 사용하기 쉬울 것입니다.한다면a이고, 그 다음에 "는 포인터입니다.a[N]다음과 같이 확장됩니다.start_address_in_a + N * size_of_item_being_pointed_by_a이 의식인 Array[2][1]함수 내부(우리는 이 요소에 접근하고 싶습니다)Array는 단일 차원 배열에 대한 포인터이며 동일한 공식이 적용됩니다.는 찾기위대에포수바를 필요합니다.size_of_item_being_pointed_by_a가 그냥 가그냥리우▁just냥.Array[][]그것을 찾는 것은 불가능할 것이고 따라서 우리가 필요로 하는 배열 요소를 제거하는 것은 불가능할 것입니다.

크기가 없으면 포인터 산술은 배열에 사용할 수 없습니다.가 좋을까요?Array + 2: : in product : 주를앞이동니합다로으소▁the다▁produce:.Array를 2바이트 앞으로 이동( 앞으로 )합니다.3* sizeof(int) * 2바이트 앞에?

C/C++에서는 2-D 어레이도 메모리에 한 행씩 순차적으로 저장됩니다.따라서 (단일 함수에서) 다음을 수행할 수 있습니다.

int a[5][3];
int *head;

head = &a[0][0];
a[2][1] = 2; // <--

하고 있는 는 실로액중요입니다.a[2][1]이라*(head + 2*3 + 1)으로 해당 는 으개로적, 는요소의 3요다있습다니의 뒤에 .0 행, 그, 개의 .1행을 선택한 다음 인덱스를 하나 더 추가합니다.

다음과 같은 기능을 선언하는 경우:

void some_function(int array[][]) {...}

구문적으로, 오류가 아니어야 합니다.하지만, 당신이 접속하려고 할 때.array[2][3]이제 어떤 요소에 액세스해야 하는지 알 수 없습니다.반면에, 다음과 같은 것이 있습니다.

void some_function(int array[][5]) {...}

당신은 그것을 알고 있습니다.array[2][3]메모리 주소의 요소에 실제로 액세스하고 있는지 확인할 수 있습니다.*(&array[0][0] + 2*5 + 3) 함수가 두 번째 차원의 크기를 알기 때문입니다.

앞서 제안한 것처럼 다음과 같은 기능을 선언할 수 있는 다른 옵션이 있습니다.

void some_function(int *array, int cols) { ... }

이렇게 하면 이전과 동일한 "정보" 즉 열 수를 사용하여 함수를 호출할 수 있기 때문입니다.그러면 어레이 요소에 조금 다르게 액세스할 수 있습니다. 다음과 같이 기록해야 합니다.*(array + i*cols + j) 당이주쓰곳는로신곳▁you를 씁니다.array[i][j], 오류array이제 정수에 대한 포인터입니다(포인터에 대한 포인터가 아님).

이와 같은 함수를 선언할 때는 사용되는 것뿐만 아니라 배열에 대해 실제로 선언된 열 수를 사용하여 호출하도록 주의해야 합니다.예를 들어, 다음과 같습니다.

int main(){
   int a[5][5];
   int i, j;

   for (i = 0; i < 3; ++i){
       for (int j=0; j < 3; ++j){
           scanf("%d", &a[i][j]);
       }
   }

   some_function(&a[i][j], 5); // <- correct
   some_function(&a[i][j], 3); // <- wrong

   return 0;
}

C 2018 6.7.6.2는 배열 선언자의 의미를 지정하며, 제1항은 다음을 포함하여 이들에 대한 제약 조건을 제공합니다.

요소 유형은 불완전하거나 함수 유형이어서는 안 됩니다.

함선서에와 같은 void example(int Array[][]),Array[]배열 선언기입니다.따라서 요소 유형이 불완전해서는 안 된다는 제약 조건을 충족해야 합니다.은 해당선의요유다같습다니음과형은소입니다.int []크기가 지정되지 않았기 때문에 불완전합니다.

C 표준이 포인터로 조정하려고 하는 매개 변수에 대한 제약 조건을 제거하지 못할 근본적인 이유는 없습니다. 유형 과결 형입니다.int (*Array)[]는 법적 선언이며 컴파일러에 의해 수용되며 형식으로 사용될 수 있습니다.(*Array)[j].

하만은, 선문언은int Array[][]는 것을 시사합니다.Array적어도 2차원 배열과 연관되어 있으므로 형식에 사용되어야 합니다.Array[i][j]선언문이 나와도int Array[][]수용되었고 조정되었습니다.int (*Array)[]그것을 로 사용하여Array[i][j]첨자 연산자의 포인터 피연산자가 완전한 형식에 대한 포인터여야 하기 때문에 가능하지 않을 수 있으며, 요소의 주소를 계산하는 데 필요하기 때문에 이 요구 사항을 피할 수 없습니다.따라서 배열 선언자에 대한 제약 조건을 유지하는 것은 인수가 1차원 배열에 대한 포인터가 아니라 2차원 배열이 될 것이라는 의도된 표현과 일치하기 때문에 의미가 있습니다.

실제로 2D 어레이든 1D 어레이든 메모리에 한 줄로 저장됩니다.컴파일러가 다음 행에 있을 다음 숫자를 나타내는 행을 어디에서 끊어야 하는지 알려면 열 크기를 제공해야 합니다.그리고 행을 적절히 구분하면 행의 크기가 표시됩니다.

예를 들어 보겠습니다.

int a[][3]={ 1,2,3,4,5,6,7,8,9,0 };

이 배열 a는 다음과 같이 메모리에 저장됩니다.

  1  2  3  4  5  6  7  8  9  0

그러나 열 크기를 3으로 지정했기 때문에 메모리는 3자리 숫자마다 분할됩니다.

#include<stdio.h>

int main() {
   int a[][3]={1,2,3,4,5,6},i,j;
   for(i=0;i<2;i++)
   {
       for(j=0;j<3;j++)
       {
           printf("%d  ",a[i][j]);
       }
       printf("\n");
   }

}

출력:

 1  2  3  
 4  5  6  

다른 경우에는,

int a[3][]={1,2,3,4,5,6,7,8,9,0};

컴파일러는 3개의 행만 알고 있지만 각 행의 요소 수를 모르기 때문에 메모리를 할당할 수 없고 오류를 표시합니다.

#include<stdio.h>

int main() {
   int a[3][]={1,2,3,4,5,6},i,j;
   for(i=0;i<3;i++)
   {
       for(j=0;j<2;j++)
       {
           printf("%d  ",a[i][j]);
       }
       printf("\n");
   }

}

출력:

 c: In function 'main':
    c:4:8: error: array type has incomplete element type 'int[]'
    int a[3][]={1,2,3,4,5,6},i,j;
        ^

이와 관련하여 비슷한 게시물이 있습니다.아래 링크를 참고하시면 됩니다.C에서 배열을 만들고 포인터를 해당 배열에 전달하는 것이 도움이 되기를 바랍니다.

반면에 컴파일러는 전체 메모리가 선형으로 배열되어 있기 때문에 한 포인터에서 다음 포인터로 "Array"를 이동할 수 있도록 2차원으로 이동해야 합니다.

저는 이것이 멋진 접근이라고 생각했습니다.이것을 배열에 있는 요소의 주소를 계산하는 공식으로 사용할 경우:

a[i][j] = baseArrayAddress + (i + (colSize + elementSize)) + (j * (elementSize))

그러면 컴파일러가 알아야 할 유일한 것은 열의 크기이므로 알고리즘이 오프셋을 계산하기 위해 실행할 수 있도록 프로그래머로 제공해야 합니다.

행 번호는 승수 역할만 하며 프로그래머가 배열 위치의 참조를 취소하려고 할 때 제공합니다.

어레이를 때 2D 어레이, 2D 어레이입니다.anytype a[3][4]은 기속서당신실제만것은입니다.3인한블록의 4모든 유형의 객체.

a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3]

이제 다음 질문은, 왜 그럴까 하는 것입니다. 왜하면사양, 의과구조따라에언냐어,따라언구에▁of조▁because,anytype a[3][4]는 확니다장됩로실제로 됩니다.anytype (*a)[4]배열이 포인터로 붕괴하기 때문입니다.그리고 사실 그것은 또한 확장됩니다.anytype (*(*a))그러나 이제 2D 어레이의 크기가 완전히 사라졌습니다.그래서 당신은 컴파일러를 조금 도와야 합니다.

프로그램에 요청하는 경우a[2]프로그램은 1D 어레이와 동일한 단계를 수행할 수 있습니다.그것은 간단히 돌아올 수 있습니다.the 3rd element of sizeof(object pointed to)여기서 가리키는 물체는 크기가 4인 모든 유형의 물체입니다.

언급URL : https://stackoverflow.com/questions/12813494/why-do-we-need-to-specify-the-column-size-when-passing-a-2d-array-as-a-parameter

반응형