2012-08-29 18 views
6

Una cosa que siempre me confundió, el puntero del personaje. Es después de largos cuatro años que estoy de nuevo persistiendo en c.¿A qué se inicializa un puntero?

Tomemos por ejemplo el caso mencionado. ¿Por qué el puntero char se comporta de esta manera? ¿Cómo podemos abordar directamente el contenido de la punta cuando no apunta a nada o es como que el puntero almacena cosas que no sean direcciones?

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
char* charPtr="I cant understand why"; 
int* intPtr=60; 


printf("%d\n", intPtr); //displays 60 
printf("%p\n", intPtr); // displays the hex value of 60 

printf("%s\n", charPtr); // displays the wh0le string 
printf("%p\n", charPtr); // displays the start address of the string 
return 0; 

}

A continuación, el puntero int, ¿Cómo se puede aceptar el valor de 60 y de dónde se almacenan?

dejando de lado el puntero de char y malloc, ¡pensé que la idea básica del puntero era conseguir una dirección para señalar!

¿Por qué estos casos

*intptr = 60 ; // should be setting the pointee's value to 60 
    intptr = 60 ; // sets the address 

error de compilación tiro mientras

int* intPtr=60; 

coló sin obtener una dirección (o 60 tomado como la dirección, si es así por qué esto no es aceptable no en el primer caso) de la punta

Supongo que me falta algo aquí pero ¡oye! Adivina qué ? me dijeron que busque en SO!

EDITAR: Dar a la dirección apuntada por el puntero de char a un puntero int también arroja ningún error!

int8_t* intPtr= (int8_t*)0x80485c8 ; // works without casting too ! I guess addresses are acceptable. 

Desreferenciar que dará un valor equivalente a la primera I de la cadena .IS esto una buena práctica o existe alguna otra explicación a esta dejando de lado emabrgo asignación de tamaño bit byte como un int puede contener un char y entonces.. ?

Como hmjd señaló, la "sintaxis de inicialización" es el problema. No tengo problemas para escribir mi propio código, pero surge un problema cuando modifico el código de alguien.

+0

Es realmente difícil averiguar lo que realmente está preguntando. Un puntero es una variable cuyo valor suele ser la dirección de otra variable. –

+0

* Supongo que me falta algo aquí * Buen libro de programación C/tutorial, en realidad. Has hecho muchas preguntas frecuentes. –

+0

@DavidSchwartz ¡Sí! Esa es la idea básica en mí también :) pero ¿qué está pasando aquí? – Borrito

Respuesta

4

En C, una cadena literal como "No puedo entender por qué" se almacena como una matriz de char tal que la memoria está disponible durante la vida útil del programa (todas las direcciones son sacados de la nada y no están destinadas a representar cualquier plataforma específica o arquitectura):

Item  Address  0x00 0x01 0x02 0x03 
-----  -------  ---- ---- ---- ---- 
"I..."  0x00080000  'I' ' ' 'c' 'a' 
      0x00008004  'n' ''' 't' ' ' 
      0x00008008  'u' 'n' 'd' 'e' 
      0x0000800C  'r' 's' 't' 'a' 
      0x00008010  'n' 'd' ' ' 'w' 
      0x00008014  'h' 'y' 0x00 0x?? 

La cadena literal es también una expresión array, y en la mayoría de contextos una expresión de "array N-elemento de T" tipo se convertirá en escriba "puntero a T", y su valor será la dirección de la primera e lement de la matriz (las excepciones son cuando la expresión de la matriz es un operando de los operadores sizeof o unario &, o es una cadena literal que se utiliza para inicializar una matriz en una declaración).

Así que cuando se escribe

char* charPtr = "I can't understand why"; 

está copiando la dirección de la cadena literal a charPtr:

Item  Address  0x00 0x01 0x02 0x03 
----  -------  ---- ---- ---- ---- 
charPtr  0xffbe4000  0x00 0x08 0x00 0x00 

Tenga en cuenta que si la declaración había sido

char str[] = "I can't understand why"; 

str sería se han asignado como una matriz de char el tiempo suficiente para contener la cadena, y los contenidos de la cadena habrían sido copiados a ella:

Item  Address  0x00 0x01 0x02 0x03 
-----  -------  ---- ---- ---- ---- 
str   0xffbe4000  'I' ' ' 'c' 'a' 
      0xffbe4004  'n' ''' 't' ' ' 
      0xffbe4008  'u' 'n' 'd' 'e' 
      0xffbe400C  'r' 's' 't' 'a' 
      0xffbe4010  'n' 'd' ' ' 'w' 
      0xffbe4014  'h' 'y' 0x00 0x?? 

Cuando se escribe

int* intPtr = 60; 

eres inicializar el valorpuntero con 60, que no establece de modo que apunte a un entero en el anonimato con el valor 60:

Item  Address  0x00 0x01 0x02 0x03 
----  -------  ---- ---- ---- ---- 
intPtr  0xffbe4004  0x00 0x00 0x00 0x3C 

La dirección 60 probablemente no sea una dirección válida, por lo que intentar desreferenciar intPtr probablemente conduzca a un comportamiento no definido.

te hicieron por escrito algo así como

int x = 60; 
int *intPtr = &x; 

entonces tendría una situación como esta:

Item  Address  0x00 0x01 0x02 0x03 
----  -------  ---- ---- ---- ---- 
x   0xffbe4004  0x00 0x00 0x00 0x3C 
intPtr  0xffbe4008  0xff 0xbe 0x40 0x04 

En este caso, el valor de intPtr es la dirección de x.

Por último, tenga en cuenta que inicialización y asignación no son la misma cosa.

T *x = value; 

no lo hace desreferenciar x y asignar value al resultado; asigna value directamente al x. El tipo de value se trata como T *. Tenga en cuenta que debe estar recibiendo advertencias en

int *intPtr = 60; 

lo largo de las líneas de "hacer puntero desde un entero sin el molde".

6

¿Cómo podemos abordar directamente el contenido de la punta cuando no apunta a nada o es como que el puntero almacena cosas que no sean direcciones?

I que la confusión es la sintaxis de inicialización. Este:

char* charPtr="I cant understand why"; 

no lo hace desreferenciar charPtr. Es equivalente a:

char* charPtr; 
charPtr = "I cant understand why"; 

Ambos fragmentos de código almacenar la dirección de la cadena literal "I cant understand why" a la charPtr. No hay desreferenciación de un puntero que apunta a que no ocurra nada. Una variable de puntero, de cualquier tipo, puede almacenar una dirección solamente.

Este:

int* intPtr=60; 

almacena una dirección de 60 en intPtr: no int cesión o deferencing se está produciendo. No existe la variable int en este punto. El compilador debería haber emitido una advertencia en esta línea. Cualquier intento de deferencia intPtr muy probablemente causará un bloqueo.

+0

¡Creo que tienes razón! Él está pensando que "a = b"; significa "establecer el valor de la variable a en el valor de b". Pero lo que realmente significa es "establecer la variable a tal que su valor sea b". Si el valor de x es 2, 'x = 3;' intenta establecer la variable 'x' en 3, no intenta establecer 2 en 3. (El concepto básico que falta en OP es lvalues ​​versus rvalues) –

+0

@ hmjd Entonces, el puntero char es algo diferente de otro puntero al menos en este aspecto, ¿o sí? Usted dijo que int * intPtr = 60; almacena una dirección 60 en intPtr entonces si pongo una dirección válida y la desreferencia, ¿obtendré el valor independientemente del tipo? Creo que será mejor actualizar la pregunta. – Borrito

+0

@Borrito, no. La diferencia aquí es el valor inicial que asignes. Para el 'char *', está asignando una dirección válida. Para 'int *', no lo eres. Si 'int i = 4; int * intPtr = & i; 'then' intPtr' tendría la dirección de 'i' y sería legal deferencia' intPtr'. – hmjd

1

Su intPtr se inicializa para que apunte a la dirección de memoria absoluta 60. No hay una tienda de respaldo aquí.

Dado que no está desmarcando el puntero, nunca intentará leer la dirección 60 que probablemente bloquee su programa dependiendo del entorno.

En su lugar, está pasando el valor del puntero a printf que toma casi cualquier cosa como argumentos e interpreta los valores como se especifica en la cadena de formato. En su caso, interpretará la dirección del puntero en lugar del valor del puntero. La dirección es 60 para que se muestre. Si hubiera usado *intPtr, probablemente se hubiera bloqueado.

2

Cuando se escribe:

char* charPtr = "I can't understand why"; 

Esto significa que la dirección base de la cadena "No puedo entender por qué" está siendo asignado a

charPtr debido a que la cadena literal también es un puntero a esa cuerda

Se puede verse como:

the concept of string stored in an char array

Esto significa que, en charPtr la dirección base de toda la cadena se almacena .Now esto es lo que ha hecho en su código.

char *charPtr="i cant understand why"; 

Sumado a eso, si imprime declaraciones como:

printf("%c","i cant understand why"[0]);//prints i 
printf("%c","i cant understand why"[2]);//prints c 

Estos dos de printf justificar mis conceptos que la cadena "puedo entender por qué" es en sí mismo un puntero a la matriz de caracteres en el que la cadena está siendo almacenada.

Cuestiones relacionadas