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
'programing tip' 카테고리의 다른 글
상수의 병적 사용 (0) | 2020.11.23 |
---|---|
androidx로 마이그레이션 한 후 androidx.constraintlayout.ConstraintLayout 클래스 확장 오류 (0) | 2020.11.23 |
언제 RuntimeException을 잡아도 괜찮습니까? (0) | 2020.11.23 |
C / C ++ 프로그램이 main () 전에 충돌 할 수있는 방법이 있습니까? (0) | 2020.11.23 |
jstl foreach는 마지막 레코드의 요소를 생략합니다. (0) | 2020.11.23 |