2012-01-31 25 views
7

Digamos que tiene-Asignación de memoria para el arreglo de caracteres

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

Si DO-

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

Cómo sería C saber la cantidad de memoria para asignar a nombre variable como esta puede contener una gran cantidad de datos/cadena? Soy nuevo en C y estoy confundido con la asignación de memoria.

+0

No intente escribir archivos fuente en varios idiomas. Creo que la forma idiomática de administrar la memoria en C++ es con [RAII] (http://en.wikipedia.org/wiki/RAII). – pmg

+1

No, 'name' es solo un puntero, que tiene un tamaño distinto (generalmente 4 u 8 bytes). Una vez que te das cuenta de esto, lo tienes. –

Respuesta

4

No lo sabrá, tendrá que asignar memoria por separado.

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

asigna suficiente memoria para almacenar un objeto del tipo Person.
Dentro de un objeto Person el miembro name solo ocupa un espacio equivalente al tamaño de un puntero a char.
El anterior malloc solo asigna ese espacio, para poder hacer algo significativo con el puntero de miembro, tendrá que asignarle memoria por separado.

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

Ahora el miembro de name apunta a una memoria dinámica de tamaño 124 byte en el montón y se puede usar más.

Además, después de que haya terminado su uso, deberá recordar free explícitamente o terminará con una pérdida de memoria.

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

Supongo que la Q está etiquetada como inválida 'C++' ya que la OP dice * ¿Cómo sería C .... * y * Soy nuevo en C ... * Si la Q es C++, la respuesta es bastante similar para usar un ' std :: string'. –

+0

Lo etiqueté C++ porque creo que tienen similitudes en lo que respecta a la administración de la memoria. ¿O estoy equivocado? Soy nuevo en C pero no soy nuevo en la programación en general. Gracias por la respuesta súper rápida. – DragonBorn

+2

@ZiG De hecho, hay similitudes (aunque preferiría usar 'new' sobre' malloc'). Pero en C++ a menudo no tiene que meterse con la administración de memoria de bajo nivel, p. mediante el uso de 'std :: string' para cadenas, en lugar de matrices simples (o punteros), o mediante el uso de' std :: vector' en lugar de matrices dinámicas hechas a sí mismas. –

-2

Creo que deberías también es necesario asignar memoria para el atributo de nombre

0

No lo hace. Tienes que hacer eso también.

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

Tiene un puntero a una matriz de caracteres de nombre en su estructura, es decir. consumirá tantos bytes que se necesitan para representar una dirección de memoria.

Si desea utilizar realmente el campo, debe asignar memoria adicional para ello.

0

Asignará 4 bytes para el puntero name, pero no espacio para la cadena "real". Si intenta escribir allí, segregará la falla; necesita malloc (y free) por separado.

Usando string (en C++) puede ahorrar algo de dolor de cabeza

+0

Supongo que asignaría 8B en máquinas de 64b :) – Vyktor

+0

Blah, derecha:) –

2

El miembro name es sólo un puntero. El tamaño de un puntero varía con la arquitectura subyacente, pero generalmente es de 4 u 8 bytes hoy en día.

Los datos que name pueden señalar (si se asignan después) se deben disponer en un área que no coincida con el struct en absoluto.

En el nivel de idioma, el struct no sabe nada sobre la memoria a la que apunta el miembro name; tienes que administrar eso manualmente

0

Para los punteros a la estructura se le asigna suficiente memoria solo para el puntero. Tienes que crear la memoria para el char * y asignar el valor a la estructura. Asumiendo que tenía char* name alguna parte:

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

Podría simplemente usar 'stdup' para crear' who-> name'. –

+0

Supongo que te refieres a strdup? Puede hacerlo si está disponible pero no es parte del estándar ANSI C. Este ejemplo de código debe ser válido ANSI C –

+0

Nunca lo mencioné en la pregunta que se requiere ANSI C válido. Muchas implementaciones incluyen esta rutina que puede ser optimizada. –

0

miembros de puntero ocupan una palabra en mi experiencia (la dirección en la bruja los datos residen en realidad) por lo que el tamaño probablemente será de 16 bytes (suponiendo una palabra es de 4 bytes)

Como dijo el hombre anteriormente, necesita asignar memoria por separado para * nombre que liberará la memoria en otro lugar para el tamaño que desee

3

No asuma que la memoria que almacena el puntero para el nombre es la misma que la memoria que almacena el datos para el nombre. Suponiendo un tamaño de palabra de 4 bytes, se tiene lo siguiente:

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

que es: sizeof(char*) + sizeof(int) + sizeof(int) + sizeof(int). C conoce el tamaño porque le has dicho el tamaño de los elementos en la definición de estructura.

Creo que lo que está confundido acerca es la siguiente:

El contenido de la char * serán una ubicación de memoria (por ejemplo 0x00ffbe532), que es donde se almacenará la cadena real. No suponga que los contenidos de la estructura son contiguos (debido al puntero). De hecho, puedes estar bastante seguro de que no lo serán.

Por lo tanto, reiterar, por ejemplo struct Person (esto es sólo un ejemplo, los lugares no serán los mismos en un programa real.)

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

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

+0

+1 para la respuesta detallada. Gracias. – DragonBorn

+1

Por favor, no firme sus publicaciones. –

2

asigna memoria para el justo el puntero a un char. Debe hacer una asignación por separado para los contenidos.

hay otras opciones, aunque:

Si estás bien con tener una longitud máxima de tamaño fijo, que puede hacer:

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

y asignar como en su ejemplo.

O puede declarar una variable sized struct, pero no lo recomendaría esto ya que es difícil y no se puede tener más de una matriz de tamaño variable por estructura:

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

y después asignarlo como:

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