C를 사용하여 배열 반환
나는 C를 처음 접했고 배열을 다루는 메소드에 대한 도움이 필요하다. Java 프로그래밍에서 왔으므로 int [] method()
배열을 반환하기 위해 말할 수있었습니다 . 그러나 C를 사용하면 배열을 반환 할 때 포인터를 사용해야한다는 것을 알았습니다. 새로운 프로그래머이기 때문에, 내가 살펴본 많은 포럼 에서조차도 이것을 전혀 이해하지 못합니다.
기본적으로 C에서 char 배열을 반환하는 메서드를 작성하려고합니다. 배열과 함께 메서드를 returnArray라고 부릅니다. 이전 배열에서 새 배열을 만들고 포인터를 반환합니다. 이것을 시작하는 방법과 포인터가 배열에서 보내지면 포인터를 읽는 방법에 대한 도움이 필요합니다. 이것을 설명하는 데 도움을 주시면 감사하겠습니다.
배열 반환 함수를위한 제안 된 코드 형식
char *returnArray(char array []){
char returned [10];
//methods to pull values from array, interpret them, and then create new array
return &(returned[0]); //is this correct?
}
함수의 호출자
int main(){
int i=0;
char array []={1,0,0,0,0,1,1};
char arrayCount=0;
char* returnedArray = returnArray(&arrayCount); ///is this correct?
for (i=0; i<10;i++)
printf(%d, ",", returnedArray[i]); //is this correctly formatted?
}
C 컴파일러가 현재 작동하지 않기 때문에 아직 테스트하지 않았지만 이것을 파악하고 싶습니다.
C의 함수에서 배열을 반환 할 수 없습니다.이 작업을 수행 할 수도 없습니다.
char *returnArray(char array []){
char returned [10];
//methods to pull values from array, interpret them, and then create new array
return &(returned[0]); //is this correct?
}
returned
는 자동 저장 기간으로 생성되며 선언 범위를 벗어나면 (즉, 함수가 반환 될 때) 참조가 유효하지 않게됩니다.
함수 내부에 메모리를 동적으로 할당하거나 호출자가 제공 한 미리 할당 된 버퍼를 채워야합니다.
옵션 1:
함수 내부에 메모리를 동적으로 할당 (할당 취소를 담당하는 호출자 ret
)
char *foo(int count) {
char *ret = malloc(count);
if(!ret)
return NULL;
for(int i = 0; i < count; ++i)
ret[i] = i;
return ret;
}
다음과 같이 호출하십시오.
int main() {
char *p = foo(10);
if(p) {
// do stuff with p
free(p);
}
return 0;
}
옵션 2 :
호출자가 제공 한 미리 할당 된 버퍼를 채 웁니다 (호출자 buf
는 함수를 할당 하고 전달합니다)
void foo(char *buf, int count) {
for(int i = 0; i < count; ++i)
buf[i] = i;
}
다음과 같이 호출하십시오.
int main() {
char arr[10] = {0};
foo(arr, 10);
// No need to deallocate because we allocated
// arr with automatic storage duration.
// If we had dynamically allocated it
// (i.e. malloc or some variant) then we
// would need to call free(arr)
}
C의 배열 처리는 Java와 매우 다르므로 그에 따라 생각을 조정해야합니다. C의 배열은 일급 개체가 아닙니다. 즉, 배열 식은 대부분의 컨텍스트에서 "배열"을 유지하지 않습니다. C에서 "N-element array of T
"유형의 T
표현식은 배열 표현식이 연산자 sizeof
또는 단항 &
연산자 의 피연산자 이거나 또는 배열 표현식은 선언에서 다른 배열을 초기화하는 데 사용되는 문자열 리터럴입니다.
무엇보다도 이것은 배열 표현식을 함수에 전달할 수 없으며 배열 유형으로 수신 하도록합니다 . 이 함수는 실제로 포인터 타입을받습니다 :
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
에 대한 호출 foo
에서 표현식 str
은 유형 char [6]
에서 로 변환 char *
되므로의 첫 번째 매개 변수 foo
가 char *a
대신 선언 됩니다 char a[6]
. 에서 sizeof str
배열 표현식의 피연산자이기 때문에, sizeof
작업자가 어레이 (6)의 바이트 수를 얻을 수 있도록, 그것은, 포인터 형식으로 변환 아니에요.
정말로 관심 이 있다면 Dennis Ritchie의 The C의 개발을 읽어서이 치료의 출처를 이해할 수 있습니다.
결론은 함수가 배열 유형을 리턴 할 수 없다는 것입니다. 배열 표현식도 대입의 대상이 될 수 없기 때문에 좋습니다.
가장 안전한 방법은 호출자가 배열을 정의하고 주소와 크기를 쓸 함수에 전달하는 것입니다.
void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
{
...
dstArray[i] = some_value_derived_from(srcArray[i]);
...
}
int main(void)
{
char src[] = "This is a test";
char dst[sizeof src];
...
returnArray(src, sizeof src, dst, sizeof dst);
...
}
또 다른 방법은 함수가 배열을 동적으로 할당하고 포인터와 크기를 반환하는 것입니다.
char *returnArray(const char *srcArray, size_t srcSize, size_t *dstSize)
{
char *dstArray = malloc(srcSize);
if (dstArray)
{
*dstSize = srcSize;
...
}
return dstArray;
}
int main(void)
{
char src[] = "This is a test";
char *dst;
size_t dstSize;
dst = returnArray(src, sizeof src, &dstSize);
...
free(dst);
...
}
이 경우 호출자는 free
라이브러리 함수를 사용 하여 배열 할당을 취소해야 합니다.
참고로 dst
, 상기 코드에 대한 간단한 포인터 char
의 배열되지 포인터 char
. C의 포인터 및 배열 시맨틱은 첨자 연산자 []
를 배열 유형 또는 포인터 유형 의 표현식에 적용 할 수 있도록합니다 . 모두 src[i]
와 dst[i]
액세스 할 i
배열 번째의 소자 (비록 단지 src
어레이 형을 가진다).
당신은 수 의 N 요소의 배열에 대한 포인터를 선언 T
하고 비슷한 작업을 수행합니다
char (*returnArray(const char *srcArr, size_t srcSize))[SOME_SIZE]
{
char (*dstArr)[SOME_SIZE] = malloc(sizeof *dstArr);
if (dstArr)
{
...
(*dstArr)[i] = ...;
...
}
return dstArr;
}
int main(void)
{
char src[] = "This is a test";
char (*dst)[SOME_SIZE];
...
dst = returnArray(src, sizeof src);
...
printf("%c", (*dst)[j]);
...
}
위의 몇 가지 단점. 우선, 이전 버전의 C SOME_SIZE
는 컴파일 타임 상수가 될 것으로 예상 되므로 함수는 하나의 배열 크기에서만 작동합니다. 둘째, 아래 첨자를 적용하기 전에 포인터를 역 참조하면 코드가 복잡해집니다. 다차원 배열을 다룰 때 배열에 대한 포인터가 더 잘 작동합니다.
이 맛있게 나쁜 구현은 어떻습니까?
array.h
#define IMPORT_ARRAY(TYPE) \
\
struct TYPE##Array { \
TYPE* contents; \
size_t size; \
}; \
\
struct TYPE##Array new_##TYPE##Array() { \
struct TYPE##Array a; \
a.contents = NULL; \
a.size = 0; \
return a; \
} \
\
void array_add(struct TYPE##Array* o, TYPE value) { \
TYPE* a = malloc((o->size + 1) * sizeof(TYPE)); \
TYPE i; \
for(i = 0; i < o->size; ++i) { \
a[i] = o->contents[i]; \
} \
++(o->size); \
a[o->size - 1] = value; \
free(o->contents); \
o->contents = a; \
} \
void array_destroy(struct TYPE##Array* o) { \
free(o->contents); \
} \
TYPE* array_begin(struct TYPE##Array* o) { \
return o->contents; \
} \
TYPE* array_end(struct TYPE##Array* o) { \
return o->contents + o->size; \
}
main.c
#include <stdlib.h>
#include "array.h"
IMPORT_ARRAY(int);
struct intArray return_an_array() {
struct intArray a;
a = new_intArray();
array_add(&a, 1);
array_add(&a, 2);
array_add(&a, 3);
return a;
}
int main() {
struct intArray a;
int* it;
int* begin;
int* end;
a = return_an_array();
begin = array_begin(&a);
end = array_end(&a);
for(it = begin; it != end; ++it) {
printf("%d ", *it);
}
array_destroy(&a);
getchar();
return 0;
}
나는 이것이 주어진 문제에 대한 최선의 해결책이거나 선호되는 해결책이라고 말하지 않습니다. 그러나 함수가 구조체를 반환 할 수 있다는 것을 기억하는 것이 유용 할 수 있습니다. 함수는 배열을 반환 할 수 없지만 배열은 구조체로 래핑 될 수 있으며 함수는 구조체를 반환하여 배열을 전달할 수 있습니다. 고정 길이 배열에서 작동합니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef
struct
{
char v[10];
} CHAR_ARRAY;
CHAR_ARRAY returnArray(CHAR_ARRAY array_in, int size)
{
CHAR_ARRAY returned;
/*
. . . methods to pull values from array, interpret them, and then create new array
*/
for (int i = 0; i < size; i++ )
returned.v[i] = array_in.v[i] + 1;
return returned; // Works!
}
int main(int argc, char * argv[])
{
CHAR_ARRAY array = {1,0,0,0,0,1,1};
char arrayCount = 7;
CHAR_ARRAY returnedArray = returnArray(array, arrayCount);
for (int i = 0; i < arrayCount; i++)
printf("%d, ", returnedArray.v[i]); //is this correctly formatted?
getchar();
return 0;
}
I invite comments on the strengths and weaknesses of this technique. I have not bothered to do so.
In your case, you are creating an array on the stack and once you leave the function scope, the array will be deallocated. Instead, create a dynamically allocated array and return a pointer to it.
char * returnArray(char *arr, int size) {
char *new_arr = malloc(sizeof(char) * size);
for(int i = 0; i < size; ++i) {
new_arr[i] = arr[i];
}
return new_arr;
}
int main() {
char arr[7]= {1,0,0,0,0,1,1};
char *new_arr = returnArray(arr, 7);
// don't forget to free the memory after you're done with the array
free(new_arr);
}
You can do it using heap memory (through malloc() invocation) like other answers reported here, but you must always manage the memory (use free() function everytime you call your function). You can also do it with a static array:
char* returnArrayPointer()
{
static char array[SIZE];
// do something in your array here
return array;
}
You can than use it without worrying about memory management.
int main()
{
char* myArray = returnArrayPointer();
/* use your array here */
/* don't worry to free memory here */
}
In this example you must use static keyword in array definition to set to application-long the array lifetime, so it will not destroyed after return statement. Of course, in this way you occupy SIZE bytes in your memory for the entire application life, so size it properly!
Your method will return a local stack variable that will fail badly. To return an array, create one outside the function, pass it by address into the function, then modify it, or create an array on the heap and return that variable. Both will work, but the first doesn't require any dynamic memory allocation to get it working correctly.
void returnArray(int size, char *retArray)
{
// work directly with retArray or memcpy into it from elsewhere like
// memcpy(retArray, localArray, size);
}
#define ARRAY_SIZE 20
int main(void)
{
char foo[ARRAY_SIZE];
returnArray(ARRAY_SIZE, foo);
}
You can use code like this:
char *MyFunction(some arguments...)
{
char *pointer = malloc(size for the new array);
if (!pointer)
An error occurred, abort or do something about the error.
return pointer; // Return address of memory to the caller.
}
When you do this, the memory should later be freed, by passing the address to free.
There are other options. A routine might return a pointer to an array (or portion of an array) that is part of some existing structure. The caller might pass an array, and the routine merely writes into the array, rather than allocating space for a new array.
참고URL : https://stackoverflow.com/questions/11656532/returning-an-array-using-c
'Programing' 카테고리의 다른 글
표준 정규화와 달리 softmax를 사용하는 이유는 무엇입니까? (0) | 2020.07.02 |
---|---|
BigDecimal 세트 스케일 및 라운드 (0) | 2020.07.02 |
팬더 : 열의 텍스트를 여러 행으로 나누려면 어떻게합니까? (0) | 2020.07.02 |
단어에서 음절 감지 (0) | 2020.07.02 |
HTML 제출 버튼 : 다른 값 / 버튼 텍스트? (0) | 2020.07.02 |