배열을 반환하기 위한 C 함수 선언
어레이를 반환하는 함수를 만들려면 어떻게 해야 합니까?이거 먹어봤어
const int WIDTH=11;
const int HEIGHT=11;
int main() {
char A[WIDTH][HEIGHT];
A=rand_grid(WIDTH,HEIGHT);
return 0;
}
// Initializes a random board.
char[][] rand_grid(int i, int k) {
char* A[i][k];
for(j=0;j<i;++j) {
for(l=0;l<k;++l) {
A[j][l]=ran(10);
}
}
return A;
}
// Returns a random number from the set {0,...,9}.
int ran(int i) {
srand((unsigned int) time(0));
return(rand()%10);
}
몇 가지 짚고 넘어가야 할 것이 있습니다.
우선 다음과 같이 어레이 개체를 할당할 수 없습니다.
char A[WIDTH][HEIGHT];
A=rand_grid(WIDTH,HEIGHT);
어레이 유형의 개체는 수정할 수 없습니다.
둘째, C의 함수는 어레이 유형을 반환할 수 없습니다.단, 다음과 같이 포인터를 어레이에 반환할 수 있습니다.
char (*foo(int width))[HEIGHT]
{
/**
* dynamically allocate memory for a widthxHEIGHT array of char
*/
char (*newArr)[HEIGHT] = malloc(sizeof *newArr * width);
/**
* initialize array contents here
*/
return newArr;
}
이 구문은 약간 혼란스럽습니다.
foo -- foo
foo(int width) -- is a function
-- taking an int parameter
*foo(int width) -- returning a pointer
(*foo(int width))[HEIGHT] -- to a HEIGHT-element array
char (*foo(int width))[HEIGHT] -- of char
C89의 경우 위 스니펫의 HEIGHT는 컴파일 시간 상수 적분식(매크로, 숫자 리터럴 또는 매크로 및/또는 숫자 리터럴로 구성된 산술식)이어야 합니다.그것이 C99에도 해당되는지 확실하지 않습니다.
투고해 주신 스니펫에 근거해, 이미 할당한 어레이를 가져와, 그 컨텐츠를 초기화합니다.대부분의 컨텍스트에서 어레이 유형의 식은 기본 유형에 대한 포인터로 암묵적으로 변환됩니다.IOW, T의 N 요소 배열을 함수에 전달하면 함수가 실제로 수신하는 것은 T에 대한 포인터입니다.
void foo (T *p) {...}
...
T arr[N];
foo(arr);
2-D 어레이의 경우 조금 더 추합니다.
void foo (T (*p)[M]) {...}
...
T arr[N][M];
foo(arr);
이는 또한 컴파일 시 M을 알고 있어야 함수의 유용성을 제한할 수 있습니다.원하는 것은 임의의 크기의 2차원 배열에 대응할 수 있는 기능입니다.이 작업을 수행하는 가장 좋은 방법은 포인터를 배열에 전달하는 대신 배열의 첫 번째 요소 주소를 전달하고 행과 열의 수를 별도의 매개 변수로 전달하는 것입니다.
void foo(T *base, size_t rows, size_t cols) {...}
...
T arr[N][M];
foo (&arr[0][0], N, M);
따라서 rand_grid 함수는 다음과 같습니다.
void rand_grid(char *base, size_t rows, size_t cols)
{
size_t i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
/**
* Since base is a simple char *, we must index it
* as though it points to a 1-d array. This works if
* base points to the first element of a 2-d array,
* since multi-dimensional arrays are contiguous.
*/
base[i*cols+j] = initial_value();
}
}
}
int main(void)
{
char A[WIDTH][HEIGHT];
rand_grid(&A[0][0], WIDTH, HEIGHT);
...
}
- 은 「 」라고 해도.
&A[0][0]
★★★★★★★★★★★★★★★★★」A
동일한 값(A의 기본 주소)을 산출하며, 두 식의 유형이 다릅니다.를 가리키는 단순한 됩니다.char *
배열에 2d 문자 ('2d 문자')는 'char' ('char')로 평가됩니다.char (*)[HEIGHT]
그럴수는 없어요.포인터를 매개 변수로 배열에 전달하여 함수에서 수정하도록 할 수도 있고 함수 자체가 데이터를 할당하여 포인터를 반환할 수도 있습니다.
당신의 경우
void rand_grid(char A[WIDTH][HEIGHT]) {
A[0][0] = 'A'; // or whatever you intend to do
}
main() {
char A[WIDTH][HEIGHT];
rand_grid(A);
}
편집: 카페가 지적한 바와 같이 실제로 반환할 수 있는 것은struct
물론 제정신인 C프로그래머는 그렇게 하지 않을 겁니다
스택 할당("")은 반환할 수 없습니다.auto
") 원시(값) 유형 이외의 변수 및struct
그런 것 같아요.그 외의 타입의 경우는, 다음의 방법으로, 히프에서 메모리를 할당할 필요가 있습니다.malloc()
또는 (크기) 어레이를 랩하여struct
.
고정 사이즈 어레이를 사용하고 있는 경우는, 이 어레이를 모델화할 수 있습니다.struct
structure-return을 사용합니다.
#define WIDTH 11
#define HEIGHT 11
typedef struct {
unsigned char cell[WIDTH * HEIGHT];
} Board;
Board board_new(void)
{
Board b;
size_t i;
for(i = 0; i < sizeof b.cell / sizeof *b.cell; i++)
b.cell[i] = rand() & 255;
return b;
}
이는 정상이며 명시적 포인터를 사용하는 다른 방법보다 비용이 많이 들지 않습니다.
void board_init(Board *b);
앞의 structure-return 케이스는 (컴파일러에 의해) 후자로 다시 쓰여질 수 있기 때문입니다.이를 반환값 최적화라고 합니다.
이렇게 하려면 어레이 A를 정적 상태로 만들 수 있습니다. 이렇게 하면 A의 스토리지가 기능 범위에 따라 결정되지 않으므로 실제로 어레이를 반환할 수 있습니다(물론 포인터 형식으로).
그러나 이는 달성하고자 하는 것을 달성하기 위한 좋은 방법은 아닙니다.어레이를 기능을 위해 넘겨주세요.rand_grid
그게 바로 주소별 패스(pass by address)의 의미입니다.
함수에서 배열을 반환하는 모든 방법에는 약점과 강점이 있습니다.
스트럭으로 감싸면 메모리 할당 및 개방에 따른 오버헤드를 피할 수 있을 뿐만 아니라 개방에 대한 기억도 피할 수 있습니다.이러한 문제는 malloc, calloc 및 realloc을 사용하는 솔루션에서 발생합니다.한편, 구조내에서 래핑 하려면 , 어레이의 최대 사이즈를 알 필요가 있어, 대규모 어레이의 메모리나 실행 시간이 낭비됩니다(예를 들면, 파일을 메모리에 로드해, 카피에 의해서 기능간에 파일 컨텐츠를 건네주는 것).
언급URL : https://stackoverflow.com/questions/1453410/declaring-a-c-function-to-return-an-array
'programing' 카테고리의 다른 글
Spring Rest Template로 폼 데이터를 POST하는 방법 (0) | 2022.06.06 |
---|---|
형제 구성 요소에 대한 vue.js의 렌더링 순서를 제어하는 방법 (0) | 2022.06.06 |
vuejs에서 데이터 개체를 복사하고 속성을 제거하면 원래 개체에서도 속성이 제거됩니다. (0) | 2022.06.06 |
Vuex 스토어에서 사용할 수 있는 값이 반응하지 않음 (0) | 2022.06.06 |
비동기 API 호출 후 vuex getter를 사용하는 방법 (0) | 2022.06.06 |