2012-02-27 3 views
2

를 구조체 할 (a 루프)가 I과 같이 어레이에 사용자를 추가하고 함수배열 함수, I 이러한 구조체 포인터의 포인터 배열이 외부 그때 너무</p> <pre><code>Person **people; </code></pre> <p>같이, 만약 그렇게</p> <pre><code>typedef struct person { int id; char name[20]; } Person; </code></pre> <p>같은 구조체가

Person person; 

for (i = 0; i < 50; i++) 
{ 
    person.id = i; 
    person.name = nameArray[i]; 
    people[i] = &person; 
} 

person는 01,230에 추가되고배열하지만 (VS2010에서) Watch 화면으로 이동하여 입력하십시오. people, 50 다음 사람을 추가 할 때와 마찬가지로 모든 슬롯에 동일한 person이 표시되는 것처럼 모든 이전 변경됩니다. 여기서 내가 뭘 잘못하고 있니?

또한 특정 인물의 이름을 검색하려면 올바른 구문입니까?

people[0] -> name; 아니면 people[0][0].name입니까?

감사합니다. 난 그냥 모든 칸에 같은 '사람'을 참조

+1

삭제 된 질문에 대한 Sidenote : 삭제 한 질문에 대한 답변을 http://stackoverflow.com/questions/9485491/read-string-from-stdin-maintain-string-length 방금 작성했습니다. –

+0

죄송합니다. 사이트에 대해 매우 생산적인 질문이 아닐 수도 있음을 느꼈습니다. –

+0

신경 쓰지 마세요. 아이디어는 :'fscanf'를 호출하기 전에 전체'char [20]'를 모두 '\ 0'으로 설정하십시오. 'fscanf'가 리턴 한 후에'for (int i = 19; i> = 0; i--) {if (s [i] == '\ 0') s [i] = ''; else break;}'. –

답변

9

무엇을 기대합니까? 모든 포인터가 같은 Person을 가리키고 있습니다. person이 범위를 벗어나면 배열의 모든 포인터 (모두 동일 함)가 유효하지 않게되고 할당 해제 된 메모리 블록을 가리 킵니다. 당신은 동적 스토리지를 할당하는 루프의 각 반복에 malloc을 사용하여 멀리 free 그것까지 갈 것 Person 만들 수 있습니다

for (i = 0; i < 50; i++) 
{ 
    Person *person = malloc(sizeof(Person)); 
    person->id = i; 
    person->name = nameArray[i]; 
    people[i] = person; 

    /* or: 
    people[i] = malloc(sizeof(Person)); 
    people[i]->id = i; 
    people[i]->name = nameArray[i]; 

    it does the same thing without the extra temporary variable 
    */ 
} 

// then when you are done using all the Person's you created... 
for (i = 0; i < 50; ++i) 
    free(people[i]); 

을 다른 방법을, 당신은 Person의 배열을 대신 Person*

Person people[50]; 

Person person; 

for (i = 0; i < 50; i++) 
{ 
    person.id = i; 
    person.name = nameArray[i]; 
    people[i] = person; // make a copy 
} 

을 그리고 그 방법으로 당신은 free 아무것도하지 않습니다들과 무슨 일을 작동합니다.

+3

+1 수정 같이 맑음. – cnicutar

+0

@cnicutar 감사합니다. 당신에게서 오는 것은 그 무엇인가 의미합니다. –

2

...

마우스 오른쪽 단추로, 같은 Person 각 시간을 사용하기 때문이다. 해당 멤버를 다시 할당하므로 마지막 할당 스틱과 포인터가 모두 동일한 메모리 덩어리를 가리 킵니다.

자동 저장 기간 (즉, 할당 된 스택)이있는 변수의 주소를 저장하고 있다는 것을 알고 있습니다. 그 메모리는 함수가 끝나고 나중에 이들 포인터 중 하나를 참조 해제하면 정의되지 않은 동작이 발생할 때 정리 될 것입니다 (아마).

함수에서 배열을 초기화하고 함수가 종료 될 때 유효하게 유지해야하는 경우 동적 할당을 사용해야합니다.

1

은 각 사람을 위해 메모리를 할당 할 필요가 :

for (i = 0; i < 50; i++) 
{ 
    people[i] = (person*)malloc(sizeof(person)); // dynamic memory allocation 
    people[i]->id = i; 
    people[i]->name = nameArray[i]; 
} 

에 변경됩니다 같은 데이터를 가리키는 포인터의 무리를 그래서 person&person는, 원래 버전에서 변경되지 않습니다 주소, 모든 반복.

0

person에 대해 공간을 할당해야합니다. 귀하의 코드는 지금 당장은 하나의 person 구조체를 가지고 있으며,이 모든 포인터는 동일한 주소를 가리키고 있습니다. 당신이 쓴 방식, 당신이 사람의 동일한 인스턴스에 대한 각 포인터를 초기화했기 때문에

1

, 검사 :

Person person; // this allocates a single person 

for (i = 0; i < 50; i++) 
{ 
    person.id = i; 
    person.name = nameArray[i]; 
    people[i] = &person; 
} 

을 그렇게 같이 동적으로 각 사람을 할당하기 만하면 무엇 :

for (i = 0; i < 50; i++) 
{ 
    Person* person = (Person*)malloc(sizeof(Person)); 
    person->id = i; 
    person->name = nameArray[i]; 
    people[i] = person; 
} 
당신은 당신의 코드 끝에 때문에, 완료 후

모든 메모리를 해제하는 것을 잊지 마세요 :

int i; 
for (i=0; i<50; i++) 
    free(people[i]); 
free(people); 
0

다른 답변은 모두 정확합니다. 추가 할 수있는 유일한 방법은 새로 Person을 만들지 않고 힙을 사용해야 할 때도 스택에 할당하는 것입니다. 기존 코드에 다음 "빠른 변화가"나쁜 이유를 이해하십시오 :

for (i = 0; i < 50; i++) 
{ 
    Person person; /* <--- BAD. Make sure you understand why. */ 

    person.id = i; 
    person.name = nameArray[i]; 
    people[i] = &person; 
} 

이 사람을 만드는 기존의 방법을 사용하여, 새로운 Person 때마다 수 있습니다. 다시 말하지만 이것이 틀린 이유와 다른 답변 (malloc 사용)이 올바른지 이해해야합니다.

관련 문제