C에서 구조체 배열을 어떻게 만드나요?


101

각 구조체가 천체를 나타내는 구조체 배열을 만들려고합니다.

나는 구조체에 대한 경험이 많지 않기 때문에 전체 배열 대신에 구조체를 사용하기로 결정했습니다. 그러나 나는 계속해서 수많은 다른 오류가 발생합니다. 다양한 스레드와 StackOverflow (예 : CC의 구조체 배열-구조체 배열 초기화) 에서 본 기술을 구현하려고 시도했지만 모두 적용 할 수있는 것은 아닙니다.

이 글을 읽어보신 분들을위한 추가 정보 : 저는이 중 어떤 것도 동적 일 필요는 없습니다. 모든 것의 크기를 미리 알고 / 정의합니다. 또한 인수를 정의한 여러 다른 메서드 (예 : GLUT 메서드)에서이 항목에 액세스하므로 전역 배열이되어야합니다.

이것은 헤더에서 구조체를 정의하는 방법입니다.

struct body
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
};

구조체의 내부를 정의하기 전에 정의하고있는 다른 전역 변수 목록이 있으며 그중 하나는이 구조체의 배열입니다 위의 항목 위에 있음) :

struct body bodies[n];

아시다시피, n제가 합법적으로 정의한 것입니다 (예 :) #define n 1.

이 배열을 여러 가지 다른 방법으로 사용하지만 가장 쉽고 공간을 적게 차지하는 배열은 메인의 단순화 된 형태입니다. 여기에서는 각 구조체의 모든 변수를 초기화하여 어떤 식 으로든 수정하기 전에 변수를 확실하게 설정합니다.

  int a, b;
 for(a = 0; a < n; a++)
 {
        for(b = 0; b < 3; b++)
        {
            bodies[a].p[b] = 0;
            bodies[a].v[b] = 0;
            bodies[a].a[b] = 0;
        }
        bodies[a].mass = 0;
        bodies[a].radius = 1.0;
 }

내가 직면 한 현재 오류는 nbody.c:32:13: error: array type has incomplete element type32 행이 구조체 배열을 만드는 곳입니다.

마지막 설명은, 헤더 나는 위의 공간을 의미 int main(void)하지만 같은에서 *.c파일을.


글쎄, 그것은 나를 위해 잘 작동합니다. 선언 struct body bodies[n];하기 전에 struct body {}선언하지 않습니까?
Jack

가변 길이 배열을 사용하면 배열의 크기가 시스템의 프로그램 스택 크기를 초과 할 때 (프로그래머가 완전히 제어 할 수없는) 신비한 버그 또는 충돌이 발생할 수 있습니다. 이런 종류의 경우 malloc ()을 사용하는 것이 좋습니다.
adrian

답변:


107
#include<stdio.h>
#define n 3
struct body
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
};

struct body bodies[n];

int main()
{
    int a, b;
     for(a = 0; a < n; a++)
     {
            for(b = 0; b < 3; b++)
            {
                bodies[a].p[b] = 0;
                bodies[a].v[b] = 0;
                bodies[a].a[b] = 0;
            }
            bodies[a].mass = 0;
            bodies[a].radius = 1.0;
     }

    return 0;
}

이것은 잘 작동합니다. 당신의 질문은 그다지 명확하지 않았으므로 소스 코드의 레이아웃을 위와 일치 시키십시오.


또한 구조체 유형의 선언과 실제로 인스턴스를 만드는 사이의 배치에 대한 질문이 있습니다. 다른 구조체가 있습니다.이 구조체는 처음 인스턴스를 만들 때 아래 의 내용을 정의 했습니다. 이번에는 어레이가 아니라), 왜 이것이 엄청난 일련의 오류를 만들지 않았습니까? 그것은 잘 작동했기 때문에 어레이를 만들려는 시도도 효과가 있었어야한다고 생각했지만 이번에는 작동하지 않았습니다. 또한 귀하의 답변에 감사드립니다.
Amndeep7

1
안녕하세요, .... 좋아요 59 개? 나는 단지 강타 ...에서 변수의 배열을 참조 구조체의 배열을 보지 못했다

12

나는 당신도 그렇게 쓸 수 있다고 생각합니다. 나는 또한 학생이기 때문에 당신의 어려움을 이해합니다. 조금 늦은 응답이지만 괜찮습니다.

#include<stdio.h>
#define n 3

struct {
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
}bodies[n];

11

따라서 다음을 사용하여 모두 정리하십시오 malloc().

int main(int argc, char** argv) {
    typedef struct{
        char* firstName;
        char* lastName;
        int day;
        int month;
        int year;

    }STUDENT;

    int numStudents=3;
    int x;
    STUDENT* students = malloc(numStudents * sizeof *students);
    for (x = 0; x < numStudents; x++){
        students[x].firstName=(char*)malloc(sizeof(char*));
        scanf("%s",students[x].firstName);
        students[x].lastName=(char*)malloc(sizeof(char*));
        scanf("%s",students[x].lastName);
        scanf("%d",&students[x].day);
        scanf("%d",&students[x].month);
        scanf("%d",&students[x].year);
    }

    for (x = 0; x < numStudents; x++)
        printf("first name: %s, surname: %s, day: %d, month: %d, year: %d\n",students[x].firstName,students[x].lastName,students[x].day,students[x].month,students[x].year);

    return (EXIT_SUCCESS);
}

8
malloc 줄에 numStudents * sizeof (STUDENT)가 있어야합니까?
Todd

@Todd하지 않는 것이 좋습니다. sizeof *studentsSTUDENT가 변해도 틀리지 않습니다.
trentcl

@trentcl 그는 {numStudents} 양의 포인터에 메모리를 할당했습니다. 구조가 아니라 포인터. 포인터 크기는 가장 일반적으로 4 바이트이고 구조 크기는 20 바이트입니다. 20 바이트는 4로 나눌 수있는 숫자이므로 패딩이 필요하지 않으며 시작 주소에서 20 번째 바이트마다 구조가 저장됩니다. 특정 경우에만 메모리를 할당하기 때문에 작동합니다. 그렇지 않으면 다른 malloc이 구조의 메모리를 덮어 쓸 수 있습니다. 그 이유는 할당되지 않았고 학생 메모리가 넘 쳤기 때문입니다.
John Smith

3
@JohnSmith 당신은 착각합니다; 다시 읽어보세요. sizeof *students의 크기 에 뾰족한 무엇 , 즉 sizeof(STUDENT), 없습니다 sizeof(STUDENT*). 당신은 ptr = malloc(num * sizeof *ptr)관용구가 경계해야하는 정확한 실수를하고 있습니다. 여기에서 확인 하십시오 (대부분의 최신 PC와 마찬가지로 서버에는 8 바이트 포인터가 있으므로 크기는 4와 20이 아닌 8과 32입니다).
trentcl

@trentcl 설명해 주셔서 감사합니다. 자체 초기화에서 포인터를 역 참조하는 구문에 혼란스러워했습니다. 조금 혼란 스럽지만 확실히 더 컴팩트 한 솔루션이라고 말하고 싶습니다.
John Smith

8

움직임

struct body bodies[n];

이후에

struct body
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
};

나머지는 모두 괜찮아 보입니다.


6

구조체 배열을 초기화하는 또 다른 방법은 배열 멤버를 명시 적으로 초기화하는 것입니다. 이 접근 방식은 구조체 및 배열 멤버가 너무 많지 않은 경우 유용하고 간단합니다.

typedef지정자를 사용하여 struct구조체 변수를 선언 할 때마다 문을 다시 사용하지 않도록 합니다.

typedef struct
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double mass;
}Body;

그런 다음 구조체 배열을 선언하십시오. 각 요소의 초기화는 선언과 함께 진행됩니다.

Body bodies[n] = {{{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0}, 
                  {{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0}, 
                  {{0,0,0}, {0,0,0}, {0,0,0}, 0, 1.0}};

반복해서 말하면, 배열 요소와 큰 구조체 멤버가 너무 많지 않고 언급했듯이 더 동적 인 접근 방식에 관심이없는 경우 다소 간단하고 직접적인 솔루션입니다. 이 접근 방식은 구조체 멤버가 명명 된 열거 형 변수 (위의 예와 같은 숫자뿐만 아니라)로 초기화 된 경우에도 유용 할 수 있습니다. 이렇게하면 코드 판독기에서 구조체와 해당 멤버의 목적과 기능에 대한 더 나은 개요를 제공합니다. 응용 프로그램.


1
이거 너무 좋아! 멋지고 간단한 답변 👍
Ethan

1

컴파일러는 당신이 헤더 파일에 구조체의 정의를 가지고 말을하고 있기 때문에, 구조체의 배열의 선언 전에 구조체의 유형의 정의를 찾을 수 없습니다 및 오류에 있는지 그 오류 수단 nbody.c다음 헤더 파일을 올바르게 포함하고 있는지 확인해야합니다. 을 확인 #include하고 해당 유형의 변수를 선언하기 전에 구조체의 정의가 완료되었는지 확인하십시오.


나는 OP가 그의 nbody.c 파일에있는 구조체 배열 선언 이전에 "아래 줄이 위의 항목 위에있다"라고 쓴 것처럼 헤더 파일로 헤더를 의미하는지 의심합니다. 그가 일어나서 의심을 제거 할 때까지 기다립니다.
NIMS

@nims는 정확합니다. 헤더는 main문장 위의 영역을 의미합니다 .
Amndeep7

1

포인터를 사용한 솔루션 :

#include<stdio.h>
#include<stdlib.h>
#define n 3
struct body
{
    double p[3];//position
    double v[3];//velocity
    double a[3];//acceleration
    double radius;
    double *mass;
};


int main()
{
    struct body *bodies = (struct body*)malloc(n*sizeof(struct body));
    int a, b;
     for(a = 0; a < n; a++)
     {
            for(b = 0; b < 3; b++)
            {
                bodies[a].p[b] = 0;
                bodies[a].v[b] = 0;
                bodies[a].a[b] = 0;
            }
            bodies[a].mass = 0;
            bodies[a].radius = 1.0;
     }

    return 0;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.