2010-05-11 14 views
11

Creo que entiendo bastante bien las referencias y los punteros. Esto es lo que yo (creo que) sé:Descripción de los punteros de C++ (cuando apuntan a un puntero)

int i = 5; //i is a primitive type, the value is 5, i do not know the address. 
int *ptr; //a pointer to an int. i have no way if knowing the value yet. 
ptr = &i; //now i have an address for the value of i (called ptr) 
*ptr = 10; //Go to the value in ptr, use it to find a location and store 10 there 

No dude en comentar o corregir estas afirmaciones.

Ahora estoy tratando de dar el salto a matrices de punteros. Esto es lo que no sé:

char **char_ptrs = new char *[50]; 
Node **node_ptrs = new Node *[50]; 

Mi entendimiento es que tengo 2 arrays de punteros, un conjunto de punteros a caracteres y uno de los nodos. Así que si quería establecer los valores, me gustaría hacer algo como esto:

char_ptrs[0] = new char[20]; 
node_ptrs[0] = new Node; 

Ahora tienen un puntero, en la posición 0 de mi matriz, en cada matriz respectiva. De nuevo, siéntete libre de comentar aquí si estoy confundido.

Entonces, ¿qué hace el operador **? Del mismo modo, ¿qué está poniendo un solo * al lado de la creación de instancias (* [50])? (¿cómo se llama exactamente, instanciación?)

+3

* ptr = 10 no es "vaya a obtener el valor almacenado en ptr y cámbielo a 10". Debería ser "Ir al valor en ptr, usarlo para buscar otra ubicación y almacenar 10 allí". Ese es el punto de desreferenciar el puntero. – Uri

+0

@Uri bien conocido. editado y actualizado. – Stephano

+0

Debo señalar que este libro fue extraordinariamente útil para aprender sobre los indicadores en C: comprensión y uso de los indicadores C de Richard Reese. Yo recomendaría esto a cualquier persona que aprenda C o C++, ya que los conceptos que contiene son invaluables. – Stephano

Respuesta

7

Algunos comentarios:

*ptr = 10; // Doesn't need to "go get" the value. Just overwrites it. 

también:

char **char_ptrs = new char *[50]; 
Node **node_ptrs = new Node *[50]; 

Es más fácil pensar que tiene dos matrices. Sin embargo, técnicamente (y en lo que respecta al compilador) lo que tiene son dos punteros. Uno es un puntero a un (puntero a un char) y el otro es un puntero a un (puntero a un nodo).

Esto se ve fácilmente por las declaraciones de sus variables, que, por cierto, puede ser más fácil de leer de derecha a izquierda:

char **char_ptrs 

lectura de derecha a izquierda: char_ptrs es un puntero a un puntero a char

pone un * junto a un puntero propiamente se llama eliminación de referencias ese puntero. Como las matrices no existen técnicamente, el operador [] en las matrices también es una operación de desreferenciación: arr[i] es otra forma de escribir *(arr + i). Para comprender esto correctamente, debe estar familiarizado con pointer arithmetic.

Más de un consecutivo * s: cada uno desreferencia el resultado de la expresión que opera. Por eso, cuando escribía:

char c = **char_ptrs; 

lo que ocurre es:

char_ptrs es un puntero a un puntero a un char. Al desviarla una vez (para el extremo derecho *) obtiene su valor, que es un puntero a un char. Desreferenciando ese valor (para el extremo izquierdo *) le da su propio valor por turno, que es un char. Al final, c contiene el valor de la char almacenada en la memoria en el lugar al que apuntaba el puntero con los puntos char_ptrs (en otras palabras, el primer puntero en su matriz).

Por el contrario, si escribe **char_ptrs = 'a';, entonces está cambiando el valor en esa ubicación de memoria.

+0

+1 bien dicho. excelente enlace también. – Stephano

+0

Nodo * tmp = node_ptrs [0]; Entonces, ¿es correcto? – Stephano

+0

@Stephano: claro que sí. – Jon

6

** es sólo * dos veces, por lo que un puntero a un puntero.

Cuando se coloca junto a un tipo, * se une a la izquierda, no a la derecha. Diciendo new char *[50] es en realidad new char* [50] y crea una matriz de 50 char*.

2

Las declaraciones hechas en su primer fragmento de código son todas correctas.

char **char_ptrs = new char *[50]; 

... significa que tiene una matriz de 50 char * s.

Su Evaluación de la

char_ptrs[0] = new char[20]; 
node_ptrs[0] = new Node; 

es correcto también.

** simplemente significa un 'puntero a un puntero'. No es un operador.

Cuando se escribe

new char *[50]; 

... ustedes están diciendo 'asignar almacenamiento para 50 char * s'.

+0

A veces la sintaxis es confusa. Prefiero: "char ** char_ptrs = new char * [50];" Para hacerlo explícito, pero esto también tiene sus desventajas. –

0

Aclaración de la primera sección:

int i = 5; // i is a primitive type, the value is 5, the address is retrieved via &i. 
int *ptr; // an unassigned pointer to an int 
ptr = &i; // ptr now point to the address of variable i 
*ptr = 10; // access (dereference) the value through ptr and change it to 10 (same as i=10) 

No hay ningún operador **, * solo operador. Como han dicho los demás, ** declara un puntero a un puntero. Como está declarando matrices de punteros y los punteros se declaran con el operador *, debe declararlos como tales al asignar memoria para ellos con new. Por lo tanto, tiene:

char **char_ptrs = new char *[50]; // allocates memory for 50 contiguous char* (pointers) 
Node **node_ptrs = new Node *[50]; // allocates memory for 50 contiguous Node* (pointers) 

Los punteros a los punteros no tienen necesariamente que declarar matrices. Puede muy bien haber un puntero normal a la que apunta otro puntero, como en:

char i = 'p'; 
char *myptr = &i; 
char **mysecondptr = &myptr; 
3

Si encuentra que la notación * difícil de leer utilización typedef para ayudar a que su código fácil de leer.

typedef char*  CharPtr; 
typedef CharPtr* CharPtrPtr; 
// Alternative to the line above 
// typedef char**  CharPtrPtr; 

// When you call new. You get a ptr to the type you are newing. 
// new int returns an intPtr. new char returns a charPtr 
CharPtrPtr char_ptrs = new CharPtr[50]; 

// So new CharPtr returns a CharPtrPtr 
// In this case we return a pointer to contigious 
// chunk of memory large enough to hold 50 CharPtr objects. 
+0

No, no. Ocultar el hecho de que algo es un puntero es un estilo muy pobre, en mi humilde opinión. –

+1

Estoy de acuerdo con Neil en el caso general. Pero Ptr está bien ya que no lo estás ocultando (en mi humilde opinión). Pero dado que se trata de un ejercicio de aprendizaje solo para acostumbrarse al uso de punteros, funciona. Cuando te vuelves viejo y perezoso como yo, un Niel * es igual de fácil de leer y más rápido de escribir :-) –

Cuestiones relacionadas