C를 사용하여 어레이 반환
저는 C에 비교적 익숙하지 않기 때문에 어레이 처리 방법에 대한 도움이 필요합니다.자바 프로그래밍에서 온 저는 이렇게 말하는 것에 익숙합니다.int [] method()
어레이를 반환하기 위해 사용합니다.그러나 C에서는 어레이를 반환할 때 포인터를 사용해야 한다는 것을 알게 되었습니다.저는 초보 프로그래머로서 많은 포럼을 살펴보았는데도 전혀 이해할 수 없습니다.
기본적으로 C에 char 배열을 반환하는 메서드를 작성하려고 합니다.메서드(return Array)에 어레이를 제공합니다.이전 배열에서 새 배열을 만들고 포인터를 반환합니다.이것을 기동하는 방법이나, 포인터가 어레이로부터 송신되었을 때에 읽어내는 방법에 대해서, 도움이 필요합니다.이에 대해 설명해 주시면 감사하겠습니다.
어레이 반환 함수에 대해 제안된 코드 형식
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 배열 타입의 식T
"는 암묵적으로 "type"의 표현으로 변환됩니다.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)의 바이트 수를 얻을 수 있습니다.
정말 관심이 있다면 데니스 리치의 '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에서는 「」, 「C」가 기대됩니다.SOME_SIZE
컴파일 시간 상수가 됩니다. 즉, 함수는 하나의 배열 크기에서만 작동합니다.둘째, 첨자를 적용하기 전에 포인터의 참조를 해제해야 합니다.이치노어레이에 대한 포인터는 다차원 어레이를 다룰 때 더 효과적입니다.
이것이 주어진 문제에 대한 최선의 해결책이나 바람직한 해결책이라고 말하는 것이 아닙니다.그러나 함수는 구조물을 반환할 수 있다는 것을 기억하면 도움이 될 수 있습니다.함수는 어레이를 반환할 수 없지만 어레이를 구조체로 감싸서 반환함으로써 어레이를 반송할 수 있습니다.이것은 고정 길이 어레이에 유효합니다.
#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;
}
이 기술의 장점과 단점에 대한 의견을 구합니다.나는 그렇게 하려고 애쓰지 않았다.
여기서 보고되는 다른 응답과 마찬가지로 (malloc() 호출을 통해) 힙 메모리를 사용하여 실행할 수 있지만, 항상 메모리를 관리해야 합니다(함수를 호출할 때마다 free() 함수를 사용합니다).스태틱 어레이에서도 실행할 수 있습니다.
char* returnArrayPointer()
{
static char array[SIZE];
// do something in your array here
return array;
}
메모리 관리에 신경 쓰지 않고 사용할 수 있습니다.
int main()
{
char* myArray = returnArrayPointer();
/* use your array here */
/* don't worry to free memory here */
}
이 예에서는 어레이 정의에서 static 키워드를 사용하여 application-long 어레이 라이프 타임을 설정해야 반환문 후에 파기되지 않습니다.물론 이렇게 하면 애플리케이션 수명 전체에 걸쳐 메모리 내의 SIZE 바이트를 차지하므로 크기를 적절하게 조정하십시오.
이 맛있는 악마의 구현은 어떻습니까?
array.
#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; \
}
메인
#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;
}
이 경우 스택에 어레이를 만들고 있으며 기능 범위를 벗어나면 어레이가 할당 해제됩니다.대신 동적으로 할당된 어레이를 만들고 포인터를 반환하십시오.
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);
}
메서드는 실패가 심한 로컬스택 변수를 반환합니다.배열을 반환하려면 함수 외부에 배열을 만들고 주소별로 함수에 전달한 다음 수정하거나 힙에 배열을 만들어 해당 변수를 반환합니다.둘 다 동작합니다만, 첫 번째는, 올바르게 동작하기 위해서 동적 메모리 할당이 필요 없습니다.
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);
}
다음과 같은 코드를 사용할 수 있습니다.
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.
}
이렇게 하면 나중에 주소를 free로 전달하여 메모리를 해방할 수 있습니다.
다른 선택사항이 있습니다.루틴에서 기존 구조의 일부인 어레이(또는 어레이의 일부)로 포인터를 반환할 수 있습니다.호출자가 어레이를 전달할 수 있으며 루틴은 새 어레이에 공간을 할당하지 않고 어레이에 쓰기만 합니다.
언급URL : https://stackoverflow.com/questions/11656532/returning-an-array-using-c
'programing' 카테고리의 다른 글
PHP는 어레이를 다른 어레이에 추가합니다(array_push 또는 +가 아님). (0) | 2022.12.19 |
---|---|
MariaDB 10.3 데이터베이스 서버를 시작하지 못했습니다. (0) | 2022.12.19 |
Angular JS: 이미 디렉티브의 스코프가 있는 컨트롤러가 있는데 디렉티브의 링크 함수가 필요한 것은 무엇입니까? (0) | 2022.12.19 |
정수나 잘못된 속성 이름과 같은 이름을 가진 개체 속성에 액세스하는 방법은 무엇입니까? (0) | 2022.12.09 |
목록이 Hamcrest에서 비어 있지 않은지 확인 (0) | 2022.12.09 |