programing

함수에 다차원 변수 길이 배열 전달

bestprogram 2023. 7. 1. 09:07

함수에 다차원 변수 길이 배열 전달

비슷한 질문이 많지만, C99/C11의 가변 길이 배열 기능과 관련된 답변을 찾을 수 없었습니다.

다차원 변수 길이 배열을 C99/C11의 함수로 전달하는 방법은 무엇입니까?

예:

void foo(int n, int arr[][]) // <-- error here, how to fix?
{
}

void bar(int n)
{
    int arr[n][n];
    foo(n, arr);
}

컴파일러(g++-4.7 -std=gnu++11)는 다음과 같이 말합니다.
error: declaration of ‘arr’ as multidimensional array must have bounds for all dimensions except the first

로 바꾸면,int *arr[]컴파일러는 여전히 불평합니다.
error: cannot convert ‘int (*)[(((sizetype)(((ssizetype)n) + -1)) + 1)]’ to ‘int**’ for argument ‘2’ to ‘void foo(int, int**)’

다음 질문은 값으로 전달하는 방법과 참조로 전달하는 방법입니다.일반적으로 전체 배열을 함수에 전달할 때 해당 배열을 복사하지 않습니다.

일정한 길이의 배열을 사용하면 "일정한" 것이 의미하는 바와 같이 함수를 선언할 때 길이를 알아야 하므로 간단합니다.

void foo2(int n, int arr[][10]) // <-- ok
{
}

void bar2()
{
    int arr[10][10];
    foo2(10, arr);
}

이러한 기능에 어레이를 전달하는 것이 최선의 방법이 아니라는 것을 알고 있습니다. 그리고 저는 전혀 좋아하지 않습니다.플랫 포인터나 객체(예: std:vector) 또는 다른 방법으로 하는 것이 더 나을 수 있습니다.하지만 여전히, 저는 이론적인 관점에서 여기에 대한 답이 무엇인지 조금 궁금합니다.

C와 C++에서는 배열을 함수에 전달하는 것이 약간 재미있습니다.배열 유형의 값이 없으므로 포인터를 전달하는 것입니다.

2D 어레이(어레이 어레이가 아닌 실제 어레이)를 처리하려면 데이터 청크 두 개를 전달해야 합니다.

  • 그것이 시작되는 곳에 대한 지침
  • 한 줄의 너비

이는 C 또는 C++, VLA, 또는 없는 두 개의 개별 값입니다.

그것을 쓰는 몇 가지 방법:

가장 단순하고 어디서나 작동하지만 더 많은 수작업이 필요함

void foo(int width, int* arr) {
    arr[x + y*width] = 5;
}

VLA, 표준 C99

void foo(int width, int arr[][width]) {
    arr[x][y] = 5;
}

역방향 인수가 있는 VLA, 전달 매개 변수 선언(GNUC 확장자)

void foo(int width; int arr[][width], int width) {
    arr[x][y]=5;
}

VLA 포함 C++ (GNU C++ 확장, 끔찍하게 추함)

void foo(int width, int* ptr) {
    typedef int arrtype[][width];
    arrtype& arr = *reinterpret_cast<arrtype*>(ptr);
    arr[x][y]=5;
}

중요한 발언:

배열 유형에 너비가 포함되어 있기 때문에 2D 배열이 있는 [x][y] 표기법이 작동합니다.컴파일 시에는 VLA = 어레이 유형을 고정할 수 없습니다.

따라서: VLA를 사용할 수 없다면...

  • C에서는 처리할 방법이 없습니다.
  • C++에서 오버로드된 연산자 오버로드가 있는 프록시 클래스 없이는 이를 처리할 수 없습니다.

VLA(C99 또는 GNU C++ 확장)를 사용할 수 있는 경우...

  • 당신은 C의 그린에 있습니다.
  • 당신은 여전히 C++에서 엉망진창이 필요합니다, 대신 수업을 사용하세요.

C++의 경우,boost::multi_array확실한 선택입니다.

해결 방법

2D 어레이의 경우 두 가지를 별도로 할당할 수 있습니다.

  • 에대차포의 1원배열에 대한 T
  • 배열T

그런 다음 (A)의 포인터가 (B)의 각 행을 가리키도록 설정합니다.

설정을 하면 (를 "A"로 전달할 수 .T**그리고 그것은 잘 작동할 것입니다.[x][y]색인 작성

이 솔루션은 2D에는 좋지만, 고차원에는 점점 더 많은 보일러 플레이트가 필요합니다.또한 간접 계층이 추가되어 VLA 솔루션보다 느립니다.

또한 다음 항목에 대해 별도로 할당된 유사한 솔루션을 사용할 수도 있습니다.B의 행. C에서 이것은 루프 내의 말로크처럼 보이며, C++의 벡터 벡터와 유사합니다.그러나 이렇게 하면 전체 어레이가 하나의 블록에 포함되는 이점이 없어집니다.

이를 위한 명확한 절단 방법은 없지만 해결 방법을 사용하여 2차원 배열을 1차원 배열로 처리한 다음 함수 내부의 2차원 배열로 다시 변환할 수 있습니다.

void foo2(int n, int *arr) 
{
    int *ptr; // use this as a marker to go to next block
    int i;
    int j;

    for(i = 0; i < n; i++)
    {
        ptr = arr + i*n; // this is the starting for arr[i] ...
        for (j = 0; j < n ;j++)
        {
            printf(" %d ", ptr[j]); // This is same as arr[i][j]
        }
    }
}

void bar2()
{
    int arr[10][10];
    foo2(10, (int *)arr);
}

언급URL : https://stackoverflow.com/questions/14548753/passing-a-multidimensional-variable-length-array-to-a-function