2012-01-31 21 views
7

Powiedzmy have-Alokacja pamięci dla tablicy char

struct Person { 
    char *name; 
    int age; 
    int height; 
    int weight; 
}; 

Jeśli DO-

struct Person *who = malloc(sizeof(struct Person)); 

Jak C wiedzieć, ile pamięci przeznaczyć na nazwy zmiennej jak można to trzymać duża liczba danych/ciągów znaków? Jestem nowy w C i mylę się z przydzielaniem pamięci.

+0

Nie próbuj pisać wielojęzycznych plików źródłowych. Wierzę, że idiomatyczny sposób zarządzania pamięcią w C++ jest z [RAII] (http://en.wikipedia.org/wiki/RAII). – pmg

+1

Nie, "nazwa" jest po prostu wskaźnikiem, który ma odrębny rozmiar (zwykle 4 lub 8 bajtów). Kiedy to sobie uświadomisz, dostałeś to. –

Odpowiedz

4

Nie będzie wiedział, musisz przydzielić pamięć dla niego osobno.

struct Person *who = malloc(sizeof(struct Person)); 

Przydziela wystarczającą ilość pamięci do przechowywania obiektu typu Person.
Wewnątrz obiektu Person element name zajmuje po prostu powierzchnię równą wielkości wskaźnika do char.
Powyższe malloc po prostu alokuje tyle miejsca, aby móc zrobić cokolwiek znaczącego przy pomocy wskaźnika elementu, do którego będziesz musiał przydzielić pamięć osobno.

#define MAX_NAME 124 
who->name = malloc(sizeof(char) * MAX_NAME); 

Teraz członek name punkty do dynamicznej pamięci o rozmiarze 124 bajt na stercie i można go stosować dalej.

Ponadto, po zakończeniu użytkowania, należy koniecznie pamiętać o tym, aby uzyskać free lub w efekcie wyciek pamięci.

free(who->name); 
free(who); 
+4

Zakładam, że Q jest nieważnie oznaczony 'C++', ponieważ OP mówi * Jak C .... * i * Jestem nowy dla C ... * Jeśli Q jest C++, odpowiedź jest dość podobna do użycia ' std :: string'. –

+0

Oznakowałem to C++, ponieważ uważam, że mają podobieństwo, jeśli chodzi o Zarządzanie pamięcią. Czy ja się mylę? Jestem początkującym użytkownikiem języka C, ale nie jest on nowy w programowaniu. Dzięki za super szybką odpowiedź. – DragonBorn

+2

@ZiG Rzeczywiście istnieją podobieństwa (chociaż wolisz używać 'nowego' niż' malloc'). Ale w C++ często po prostu nie musisz zadzierać z jakimkolwiek zarządzaniem pamięciami niskiego poziomu, np. używając 'std :: string' dla łańcuchów zamiast zwykłych tablic znaków (lub wskaźników) lub używając' std :: vector' zamiast samodzielnie tworzonych dynamicznych tablic. –

-2

myślę, że należy również trzeba przydzielić pamięci dla atrybutu name

0

nie. Musisz to również zrobić.

struct Person *who = malloc(sizeof(struct Person)); 
who->name = malloc(sizeof(char) * 16); /* for a 15+1 character array */ 
0

Masz wskaźnik do tablicy znaków nazwy w Twojej strukturze, np. pochłonie tyle bajtów, które są potrzebne do reprezentowania adresu pamięci.

Jeśli chcesz rzeczywiście użyć tego pola, musisz przydzielić mu dodatkową pamięć.

0

Przydzieli 4 bajty dla wskaźnika name, ale bez spacji dla "prawdziwego" ciągu. Jeśli spróbujesz tam napisać, usuniesz błąd; musisz malloc (i free) oddzielnie.

Korzystanie string (w C++) można zaoszczędzić trochę ból głowy

+0

Myślę, że przydzieliłoby 8B na maszynach 64b :) – Vyktor

+0

Blah, prawy:) –

2

państw name to tylko wskazówka. Rozmiar wskaźnika zmienia się w zależności od architektury, ale zwykle wynosi obecnie 4 lub 8 bajtów.

Dane, które mogą wskazywać na name (jeśli przypisano później) powinny być rozmieszczone w obszarze, który nie pokrywa się z struct w ogóle.

Na poziomie języka, struct nie wie nic o pamięci, na którą wskazuje element name; musisz to zarządzać ręcznie.

0

W przypadku wskaźników struktura ma przydzieloną wystarczającą ilość pamięci tylko dla wskaźnika. Musisz utworzyć pamięć dla znaku * i przypisać wartość do struktury. Zakładając, że miał char* name gdzieś:

struct Person *who = malloc(sizeof(struct Person)); 
who->name = malloc((strlen(name)+1) * sizeof(char)); 
strcpy(who->name, name) 
+0

Może po prostu użyć 'stdup' do stworzenia' who-> name'. –

+0

Zakładam, że masz na myśli strdup? Możesz, jeśli jest dostępny, ale nie jest częścią standardu ANSI C. Ten przykład kodu powinien być prawidłowy ANSI C –

+0

Nigdy nie wspominałem o tym w pytaniu, czy poprawna ANSI C jest wymagana. Wiele wdrożeń obejmuje tę procedurę, która może zostać zoptymalizowana. –

0

członkowie Pointer zajmują jedno słowo z mojego doświadczenia (adres na czarownicę dane faktycznie przebywa), więc rozmiar będzie prawdopodobnie 16 bajtów (zakładając, że jedno słowo jest 4 bajty)

Jak powiedział człowiek, musisz oddzielnie przydzielić pamięć dla * nazwy, która zwolni pamięć w innym miejscu, dla pożądanego rozmiaru:

3

Nie zakładaj, że pamięć przechowująca wskaźnik dla nazwy jest taka sama jak pamięć przechowująca dane dla nazwy. Zakładając 4 bajtowy rozmiar tekstu, są następujące:

  • char * (4 bytes)
  • int (4 bytes)
  • int (4 bytes)
  • int (4 bytes)
  • ================
  • total: 16 bytes

, który jest: sizeof(char*) + sizeof(int) + sizeof(int) + sizeof(int). C zna rozmiar, ponieważ określiłeś rozmiar elementów w definicji struktury.

myślę, czego nie zna jest następująca:

Zawartość w char * będzie lokalizację pamięci (np 0x00ffbe532) czyli tam, gdzie będą przechowywane rzeczywisty ciąg. Nie zakładaj, że zawartość struct jest ciągła (ze względu na wskaźnik). W rzeczywistości możesz być prawie pewien, że tak nie będzie.

Więc powtórzyć, na przykład struct Person (to tylko przykład, lokalizacje nie będą takie same w prawdziwym programie.)

  • location : [contents]
  • 0x0000 : [0x00ffbe532]
  • 0x0004 : [10]
  • 0x0008 : [3]
  • 0x000C : [25]

  • 0x00ffbe532 : [I am a string\0]

+0

+1 w celu uzyskania szczegółowej odpowiedzi. Dzięki. – DragonBorn

+1

Proszę nie podpisywać swoich postów. –

2

To przydziela pamięć dla tylko wskaźnik do char. Musisz wykonać oddzielną alokację dla zawartości.

Są jeszcze inne opcje, choć:

Jeśli są OK, z konieczności stałej wielkości maksymalnej długości, można zrobić:

struct Person { 
    char name[PERSON_NAME_MAX_LENGTH+1]; 
    int age; 
    int height; 
    int weight; 
}; 

i przeznaczyć go jak w przykładzie.

Albo można zadeklarować variable sized struct, ale ja nie polecam tego, jak to jest trudne i nie można mieć więcej niż jedną tablicę zmiennej wielkości za struct:

struct Person { 
    int age; 
    int height; 
    int weight; 
    char name[]; /*this must go at the end*/ 
}; 

a następnie przydzielić to lubią:

struct Person *who = malloc(sizeof(struct Person) + sizeof(char)*(name_length+1));