programing tip

C에서 참조로 배열을 전달합니까?

itbloger 2020. 11. 23. 07:52
반응형

C에서 참조로 배열을 전달합니까?


C에서 참조로 구조체 배열을 어떻게 전달할 수 있습니까?

예로서:

struct Coordinate {
   int X;
   int Y;
};
SomeMethod(Coordinate *Coordinates[]){
   //Do Something with the array
}
int main(){ 
   Coordinate Coordinates[10];
   SomeMethod(&Coordinates);
}

C에서 배열은 첫 번째 요소에 대한 포인터로 전달됩니다. 그것들은 실제로 값으로 전달되지 않는 유일한 요소입니다 (포인터는 값으로 전달되지만 배열은 복사되지 않습니다). 이를 통해 호출 된 함수가 내용을 수정할 수 있습니다.

void reset( int *array, int size) {
   memset(array,0,size * sizeof(*array));
}
int main()
{
   int array[10];
   reset( array, 10 ); // sets all elements to 0
}

이제 원하는 것이 배열 자체 (요소 수 ...)를 변경하는 것이라면 스택 또는 전역 배열로는 수행 할 수 없으며 힙에 동적으로 할당 된 메모리로만 수행 할 수 있습니다. 이 경우 포인터를 변경하려면 포인터를 전달해야합니다.

void resize( int **p, int size ) {
   free( *p );
   *p = malloc( size * sizeof(int) );
}
int main() {
   int *p = malloc( 10 * sizeof(int) );
   resize( &p, 20 );
}

질문 편집에서 구조체 배열 전달에 대해 구체적으로 묻습니다. 거기에 두 가지 해결책이 있습니다. typedef를 선언하거나 구조체를 전달하고 있음을 명시하십시오.

struct Coordinate {
   int x;
   int y;
};
void f( struct Coordinate coordinates[], int size );
typedef struct Coordinate Coordinate;  // generate a type alias 'Coordinate' that is equivalent to struct Coordinate
void g( Coordinate coordinates[], int size ); // uses typedef'ed Coordinate

선언 할 때 유형을 typedef 할 수 있습니다 (C에서 일반적인 관용구입니다).

typedef struct Coordinate {
   int x;
   int y;
} Coordinate;

여기에 대한 답변 중 일부를 확장하려면 ...

C에서 배열 식별자가 & 또는 sizeof에 대한 피연산자 이외의 컨텍스트에 나타날 때 식별자 유형은 암시 적으로 "T의 N 요소 배열"에서 "T에 대한 포인터"로 변환되고 그 값은 다음과 같습니다. 암시 적으로 배열의 첫 번째 요소 주소로 설정됩니다 (배열 자체의 주소와 동일 함). 그렇기 때문에 배열 식별자를 함수에 대한 인수로 전달하면 함수가 배열이 아닌 기본 유형에 대한 포인터를받습니다. 첫 번째 요소에 대한 포인터를 보는 것만으로는 배열의 크기를 알 수 없으므로 크기를 별도의 매개 변수로 전달해야합니다.

struct Coordinate { int x; int y; };
void SomeMethod(struct Coordinate *coordinates, size_t numCoordinates)
{
    ...
    coordinates[i].x = ...;
    coordinates[i].y = ...; 
    ...
}
int main (void)
{
    struct Coordinate coordinates[10];
    ...
    SomeMethod (coordinates, sizeof coordinates / sizeof *coordinates);
    ...
}

배열을 함수에 전달하는 몇 가지 다른 방법이 있습니다.

T에 대한 포인터와 반대로 T의 배열에 대한 포인터와 같은 것이 있습니다. 이러한 포인터는 다음과 같이 선언합니다.

T (*p)[N];

이 경우, p는 T의 N 요소 배열에 대한 포인터입니다 (여기서 p는 T에 대한 포인터의 N 요소 배열 인 T * p [N]과 반대). 따라서 첫 번째 요소에 대한 포인터가 아니라 배열에 대한 포인터를 전달할 수 있습니다.

struct Coordinate { int x; int y };

void SomeMethod(struct Coordinate (*coordinates)[10])
{
    ...
    (*coordinates)[i].x = ...;
    (*coordinates)[i].y = ...;
    ...
}

int main(void)
{
    struct Coordinate coordinates[10];
    ...
    SomeMethod(&coordinates);
    ...
}

이 방법의 단점은 T의 10 개 요소 배열에 대한 포인터가 T의 20 개 요소 배열에 대한 포인터와 다른 유형이기 때문에 배열 크기가 고정되어 있다는 것입니다.

세 번째 방법은 배열을 구조체로 래핑하는 것입니다.

struct Coordinate { int x; int y; };
struct CoordinateWrapper { struct Coordinate coordinates[10]; };
void SomeMethod(struct CoordinateWrapper wrapper)
{
    ...
    wrapper.coordinates[i].x = ...;
    wrapper.coordinates[i].y = ...;
    ...
}
int main(void)
{
    struct CoordinateWrapper wrapper;
    ...
    SomeMethod(wrapper);
    ...
}

이 방법의 장점은 포인터를 다루지 않는다는 것입니다. 단점은 배열 크기가 고정되어 있다는 것입니다 (다시 말하면 T의 10 개 요소 배열은 T의 20 개 요소 배열과 다른 유형입니다).


C 언어는 모든 유형의 참조에 의한 전달을 지원하지 않습니다. 가장 가까운 방법은 형식에 대한 포인터를 전달하는 것입니다.

다음은 두 언어로 된 인위적인 예입니다.

C ++ 스타일 API

void UpdateValue(int& i) {
  i = 42;
}

가장 가까운 C 상당

void UpdateValue(int *i) {
  *i = 42;
}

또한 메서드 내에서 배열을 만드는 경우 반환 할 수 없습니다. 포인터를 반환하면 함수가 반환 될 때 스택에서 제거되었을 것입니다. 힙에 메모리를 할당하고 그에 대한 포인터를 반환해야합니다. 예.

//this is bad
char* getname()
{
  char name[100];
  return name;
}

//this is better
char* getname()
{
  char *name = malloc(100);
  return name;
  //remember to free(name)
}

일반 C에서는 API에서 포인터 / 크기 조합을 사용할 수 있습니다.

void doSomething(MyStruct* mystruct, size_t numElements)
{
    for (size_t i = 0; i < numElements; ++i)
    {
        MyStruct current = mystruct[i];
        handleElement(current);
    }
}

포인터를 사용하는 것은 C에서 사용할 수있는 참조 별 호출에 가장 가깝습니다.


배열은 기본적으로 참조를 통해 효과적으로 전달됩니다. 실제로 첫 번째 요소에 대한 포인터 값이 전달됩니다. 따라서이를 수신하는 함수 또는 메소드는 배열의 값을 수정할 수 있습니다.

void SomeMethod(Coordinate Coordinates[]){Coordinates[0].x++;};
int main(){
  Coordinate tenCoordinates[10];
  tenCoordinates[0].x=0;
  SomeMethod(tenCoordinates[]);
  SomeMethod(&tenCoordinates[0]);
  if(0==tenCoordinates[0].x - 2;){
    exit(0);
  }
  exit(-1);
}

두 호출은 동일하며 종료 값은 0이어야합니다.


Hey guys는 new 또는 malloc을 사용하여 배열을 할당하고 전달하는 방법을 보여주는 간단한 테스트 프로그램입니다. 잘라 내고 붙여넣고 실행하십시오. 즐기세요!

struct Coordinate
{
    int x,y;
};

void resize( int **p, int size )
{
   free( *p );
   *p = (int*) malloc( size * sizeof(int) );
}

void resizeCoord( struct Coordinate **p, int size )
{
   free( *p );
   *p = (Coordinate*) malloc( size * sizeof(Coordinate) );
}

void resizeCoordWithNew( struct Coordinate **p, int size )
{
   delete [] *p;
   *p = (struct Coordinate*) new struct Coordinate[size];
}

void SomeMethod(Coordinate Coordinates[])
{
    Coordinates[0].x++;
    Coordinates[0].y = 6;
}

void SomeOtherMethod(Coordinate Coordinates[], int size)
{
    for (int i=0; i<size; i++)
    {
        Coordinates[i].x = i;
        Coordinates[i].y = i*2;
    }
}

int main()
{
    //static array
    Coordinate tenCoordinates[10];
    tenCoordinates[0].x=0;
    SomeMethod(tenCoordinates);
    SomeMethod(&(tenCoordinates[0]));
    if(tenCoordinates[0].x - 2  == 0)
    {
        printf("test1 coord change successful\n");
    }
    else
    {
        printf("test1 coord change unsuccessful\n");
    }


   //dynamic int
   int *p = (int*) malloc( 10 * sizeof(int) );
   resize( &p, 20 );

   //dynamic struct with malloc
   int myresize = 20;
   int initSize = 10;
   struct Coordinate *pcoord = (struct Coordinate*) malloc (initSize * sizeof(struct Coordinate));
   resizeCoord(&pcoord, myresize); 
   SomeOtherMethod(pcoord, myresize);
   bool pass = true;
   for (int i=0; i<myresize; i++)
   {
       if (! ((pcoord[i].x == i) && (pcoord[i].y == i*2)))
       {        
           printf("Error dynamic Coord struct [%d] failed with (%d,%d)\n",i,pcoord[i].x,pcoord[i].y);
           pass = false;
       }
   }
   if (pass)
   {
       printf("test2 coords for dynamic struct allocated with malloc worked correctly\n");
   }


   //dynamic struct with new
   myresize = 20;
   initSize = 10;
   struct Coordinate *pcoord2 = (struct Coordinate*) new struct Coordinate[initSize];
   resizeCoordWithNew(&pcoord2, myresize); 
   SomeOtherMethod(pcoord2, myresize);
   pass = true;
   for (int i=0; i<myresize; i++)
   {
       if (! ((pcoord2[i].x == i) && (pcoord2[i].y == i*2)))
       {        
           printf("Error dynamic Coord struct [%d] failed with (%d,%d)\n",i,pcoord2[i].x,pcoord2[i].y);
           pass = false;
       }
   }
   if (pass)
   {
       printf("test3 coords for dynamic struct with new worked correctly\n");
   }


   return 0;
}

참고 URL : https://stackoverflow.com/questions/1106957/passing-an-array-by-reference-in-c

반응형