Pregunta

Soy nuevo en C y tengo esta pregunta. ¿Por qué falla el siguiente código:

int *a = 10;
*a = 100;
¿Fue útil?

Solución

Porque está intentando escribir 100 en la ubicación de memoria 0x0000000A que probablemente no esté asignada a su programa. Es decir,

int *a = 10;

no significa que el puntero 'a' apunte a una ubicación en la memoria que tenga el valor de 10. Significa que apunta a la dirección 10 (0x0000000A) en la memoria. Luego, desea escribir algo en esa dirección, pero no tiene los " derechos " para hacerlo, ya que no está asignado

Puedes probar lo siguiente:

int *a = malloc(sizeof(int));
*a = 100;

Esto funcionaría, aunque horriblemente ineficiente. Si solo necesita un solo int, debe colocarlo en la pila de , no en el montón . En una arquitectura de 32 bits, un puntero tiene una longitud de 32 bits, y un int también tiene una longitud de 32 bits, por lo que su estructura de puntero a int se desplaza ( al menos ) 8 bytes de espacio de memoria de esta manera en lugar de 4. Y ni siquiera hemos mencionado los problemas de almacenamiento en caché.

Otros consejos

Debe asignar el puntero a una ubicación de memoria , no a un valor arbitrario (10).

int cell = 10;
int *a = &cell; // a points to address of cell
*a = 100;       // content of cell changed

Consulte mi respuesta a otra pregunta, acerca de tener cuidado con C .

Me gustaría proponer un ligero cambio en el uso de malloc (), para todas las respuestas que sugieren utilizarlo para asignar memoria para el int. En lugar de:

a = malloc(sizeof(int));

Sugeriría que no se repita el tipo de variable, ya que el compilador lo conoce y, al repetirlo manualmente, hace que el código sea más denso e introduce un riesgo de error. Si luego cambia la declaración a, por ejemplo,

long *a;

Sin cambiar la asignación, terminaría asignando la cantidad de memoria incorrecta (en el caso general, en las máquinas de 32 bits int y long a menudo son las mismas tamaño). Es, IMO, mejor usar:

a = malloc(sizeof *a);

Esto simplemente significa " el tamaño del tipo al que apunta un " ;, en este caso int , que por supuesto es exactamente correcto. Si cambia el tipo en la declaración como arriba, esta línea sigue siendo correcta. Todavía existe un riesgo, si cambia el nombre de la variable en el lado izquierdo de la asignación, pero al menos ya no repite la información innecesariamente.

También tenga en cuenta que no se necesitan paréntesis con sizeof cuando se usa en objetos reales (es decir, variables), solo con nombres de tipo, que parecen expresiones de conversión. sizeof no es una función, es un operador.

Porque nunca has asignado ninguna memoria para a. Acaba de asignar un espacio de pila para un puntero a un.

int *a = NULL;

a = malloc (sizeof (int));

if (a != NULL)
{
*a =10;
}

Funcionará.

Alternativamente, puedes dar la dirección de alguna variable existente, que también funcionaría.

es decir,

int a* = NULL;
int b = 10;

a = &b;

Esto ahora significará que hacer algo como

*a = 100;

también establecerá b en == 100

Echa un vistazo a esto: http://home.netcom.com/~tjensen/ptr/pointers.pdf

La siguiente línea,

int *a = 10;

define un puntero a un entero a . Luego, apunta el puntero a a la ubicación de memoria 10.

La siguiente línea,

*a = 100;

Pone el valor 100 en la ubicación de memoria señalada por a.

El problema es:

  1. No sabes a dónde apunta. (No sabes el valor de la ubicación de memoria 10)
  2. Donde quiera que apuntes, probablemente no tienes derecho a cambiar ese valor. Probablemente sea algún otro programa / proceso de memoria ¡Tú ladrón!

Como declara un puntero a int, inicialice el puntero a 10 (una dirección) y luego intente asignar un valor a un int en esta dirección. Dado que la memoria en la dirección 10 no pertenece a su proceso, se bloquea. Esto debería funcionar:

int *a;
a = malloc(sizeof(int));
*a = 10;
printf("a=%i\n", *a);
free(a);

¿Se compila este código? 10 no se puede convertir a un int * , a menos que lo emita de esta manera:

int *a = (int *) 10;
*a = 100;

En ese caso, estás intentando escribir 100 en la dirección de la memoria con 10. Esta no suele ser una dirección de memoria válida, por lo tanto, tu programa falla.

Es probable que se bloquee porque está asignando el puntero a una parte de la memoria a la que no tiene acceso y luego le está asignando algún valor a esa ubicación de memoria (¡lo cual no puede hacer!).

También puedes escribirlo como:

int* a = 10;
*a = 100;

Note el espaciado diferente en la primera línea. No es un estilo popular, pero personalmente creo que es más claro. Tiene exactamente el mismo significado para el compilador.

Luego, léelo en voz alta:

"Pointer-to-int 'a' becomes 10"
"Value-pointed-to-by 'a' becomes 100"

Sustituyendo el valor real:

"Value-pointed-to-by 10 becomes 100"

... en el que te das cuenta de que es poco probable que 10 apunten a un fragmento de memoria que puedas usar.

Usted casi nunca asignaría un puntero con un literal:

int* ptr = (int*)10;  // You've guessed at a memory address, and probably got it wrong
int* ptr = malloc(sizeof(int)); // OS gives you a memory address at runtime  

Supongo que puede haber algunos trabajos de bajo nivel muy donde se especifican directamente las direcciones de memoria absolutas. ¿Implementación del kernel por ejemplo?

Está bien, intentar dar la explicación más simple hoy, al mismo tiempo que intentamos darte una imagen más detallada de todo esto. Vamos a agregar algunos paréntesis, ¿verdad?

(int*) a = 10;
(*a) = 100;

Intenta escribir cuatro bytes en el rango de direcciones [10-13]. El diseño de la memoria de su programa comienza generalmente más alto, por lo que su aplicación no sobrescribe accidentalmente nada de lo que podría funcionar y aún funciona (desde .data, .bss y la pila, por ejemplo). Así que simplemente termina por fallar, porque el rango de direcciones no se ha asignado.

El puntero apunta a una ubicación de memoria y la escritura estática C define un tipo para un puntero. Aunque se puede anular el puntero fácilmente. Simplemente:

(void*) v = NULL;

Aquí vamos más allá de las cosas. ¿Qué es un puntero nulo? Es simplemente un puntero que apunta a la dirección 0.

También puedes dar un tipo de estructura para tu puntero:

struct Hello {
    int id;
    char* name;
};

...

struct Hello* hello_ptr = malloc(sizeof Hello);
hello_ptr->id = 5;
hello_ptr->name = "Cheery";

Ok, ¿qué es malloc? Malloc asigna memoria y devuelve un puntero a la memoria asignada. Tiene una firma de tipo siguiente:

void* malloc(size_t size);

Si no tiene un recolector de basura conservador, es probable que su memoria no se libere automáticamente. Por lo tanto, si desea volver a utilizar la memoria de lo que acaba de asignar, debe hacer lo siguiente:

free(hello_ptr);

Cada malloc que hagas tiene una etiqueta de tamaño, por lo que no es necesario que indiques el tamaño del fragmento que apuntaste para obtener una rutina libre.

Ok, pero una cosa, ¿cómo se ve una cadena de caracteres en la memoria? El que es similar a " Cheery " por ejemplo. Respuesta simple Es una matriz de bytes terminada en cero.

0.1.2.3.4.5. 6
C h e e r y \0
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top