Выделение памяти для массива char - PullRequest
7 голосов
/ 31 января 2012

Допустим, у вас есть -

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

Если вы делаете -

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

Как C узнает, сколько памяти выделить для name переменной, так как она может содержать большое количество данных / строк? Я новичок в C и запутался с распределением памяти.

Ответы [ 10 ]

4 голосов
/ 31 января 2012

Он не будет знать, вам придется выделить память для него отдельно.

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

Выделяет достаточно памяти для хранения объекта типа Person.
Внутри Person объекта член name просто занимает пространство, эквивалентное размеру указателя на char.
Вышеупомянутый malloc просто выделяет столько места, чтобы иметь возможность делать что-либо значимое с указателем члена, вам придется выделять ему память отдельно.

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

Теперь элемент name указывает на динамическую память размером 124 байт в куче, и ее можно использовать в дальнейшем.

Кроме того, после того, как ваше использование будет завершено, вам нужно будет запомнить free это явно, или вы получите утечку памяти.

free(who->name);
free(who); 
4 голосов
/ 31 января 2012

Не думайте, что память, в которой хранится указатель для имени, совпадает с памятью, в которой хранятся данные для имени. Предполагая 4-байтовый размер слова, у вас есть следующее:

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

, что: sizeof(char*) + sizeof(int) + sizeof(int) + sizeof(int). C знает размер, потому что вы указали размер элементов в определении структуры.

Я думаю, что вас смущает следующее:

Содержимое в char * будет ячейкой памяти (например, 0x00ffbe532), где будет храниться фактическая строка. Не думайте, что содержимое структуры является смежным (из-за указателя). На самом деле, вы можете быть уверены, что их не будет.

Итак, повторим, например, struct Person (это всего лишь пример, местоположения не будут одинаковыми в реальной программе.)

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

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

2 голосов
/ 31 января 2012

Распределяет память только для указателя на символ.Вы должны сделать отдельное распределение для содержимого.

Есть и другие варианты, хотя:

Если вы в порядке с максимальной длиной фиксированного размера, вы можете сделать:

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

И выделите его, как в вашем примере.

Или вы можете объявить переменную структуру struct , но я бы не рекомендовал это, поскольку это сложно, и вы не можете иметь больше, чемодин массив переменного размера на структуру:

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

, а затем выделить его следующим образом:

struct Person *who = malloc(sizeof(struct Person) + sizeof(char)*(name_length+1));
2 голосов
/ 31 января 2012

Элемент name является просто указателем. Размер указателя зависит от базовой архитектуры, но в настоящее время обычно составляет 4 или 8 байт.

Данные, на которые может указывать name (если они назначены позже), должны быть расположены в области, которая вообще не совпадает с struct.

На уровне языка struct ничего не знает о памяти, на которую указывает член name; Вы должны управлять этим вручную.

0 голосов
/ 31 января 2012

В моем опыте члены-указатели занимают одно слово (адрес, на котором фактически располагаются данные), поэтому размер, вероятно, составит 16 байт (при условии, что одно слово составляет 4 байта)

Как сказал человек выше, вам нужно отдельно выделить память для * name witch освободит память где-то еще для нужного вам размера

0 голосов
/ 31 января 2012

Для указателей структура выделяет достаточно памяти только для указателя.Вы должны создать память для char * и назначить значение для структуры.Предполагая, что у вас было char* name где-то:

struct Person *who = malloc(sizeof(struct Person));
who->name = malloc((strlen(name)+1) * sizeof(char));
strcpy(who->name, name)
0 голосов
/ 31 января 2012

Он выделит 4 байта для указателя name, но без пробела для "реальной" строки.Если вы попытаетесь написать там, вы увидите ошибку;вам нужно mallocfree) отдельно.

Использование string (в C ++) может избавить вас от головной боли

0 голосов
/ 31 января 2012

У вас есть указатель на массив символов имени в вашей структуре, т.е. он будет использовать столько байтов, сколько необходимо для представления адреса памяти.

Если вы действительно хотите использовать это поле, вы должны выделить для него дополнительную память.

0 голосов
/ 31 января 2012

Это не так. Вы тоже должны это сделать.

struct Person *who = malloc(sizeof(struct Person));
who->name = malloc(sizeof(char) * 16); /* for a 15+1 character array */
0 голосов
/ 31 января 2012

Я думаю, вам также нужно выделить память для атрибута имени

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...