2010-02-04 20 views
22

Sé que tenemos diferentes punteros como int, float y char. Un puntero void es el único puntero que puede contener todos los demás.¿Por qué tenemos punteros distintos de vacío?

¿Los otros punteros existen solo por la flexibilidad de hacer aritmética de puntero?

¿Hay algún otro motivo por el que los punteros que no sean void estén presentes en el lenguaje C?

+1

¿Puedo saber el motivo del vencimiento? – Vijay

+3

ni idea, pero me atrevo a adivinar: ¿alguien pensó que no sabía lo suficiente sobre lo que estaba pidiendo para entender realmente una respuesta? – Will

+0

No olvide punteros a las estructuras. – phkahler

Respuesta

20

Tipo de seguridad. La definición del tipo de punteros ayuda al compilador a encontrar errores cuando intenta utilizar datos del tipo incorrecto a través de un puntero. Esa es la razón por la que C tiene tipos en primer lugar.

+3

-1, muy engañoso: la existencia de tipos no implica la existencia de seguridad tipo. Principalmente, es el hecho de que el tipo de fundido de referencia/desreferenciación de puntero es tan ilimitado que C es un tipo de lenguaje inseguro. En cambio, el punto es que los tipos describen la semántica del puntero ref/dereferencing. –

3

Cuando usa el puntero para flotar o int (por ejemplo) el compilador sabe cuántos bytes debe tomar de la memoria (sizeof (int) para int * por ejemplo).

Con vacío Usted tendría que contar cada vez con compilador cuántos bytes se tiene que tomar (por escrito (int *) some_void_ptr por ejemplo

pero esto es una gran simplificación

0

dos palabras..: Tipo de seguridad

Hay una pequeña golosina en type safety (or lack thereof) in C en la Wikipedia que podría arrojar alguna luz para usted.

+0

-1: cf. mi comentario sobre la respuesta de Max. –

8
int o = 12; 
void *i = &o; 

Cómo ¿accedería a la int que i apunta a si solo había punteros vacíos y no int *. Es posible que sepa que en su plataforma un int es de 4 bytes, por lo que podría memcpy 4 bytes desde el comienzo de lo que el vacío * apunta a un int temporal y luego usar eso. Pero eso no es muy conveniente.

O dado un

struct Pair { 
    char *first; 
    char *second; 
}; 

lo útil que sería un puntero nulo a struct Par sea? Es probable que desee acceder a su miembro first y eso es mucho trabajo si no puede tener un puntero a struct Pair.

+0

+1 por responder la pregunta sin hacer afirmaciones falsas. –

0

Cuando recorre el bloque de memoria apuntado por un puntero, es necesario conocer el tamaño del tipo de datos que contiene la memoria. Supongamos que tiene dos punteros, un char charptr y un int intptr, ambos apuntando a la memoria en el byte X. charptr + 1 apuntará al byte X + 1, mientras que intptr + 1 apuntará al byte X + 4.

Una pieza rápida y sucia de código mal escrito para ilustrar que:

#include <stdio.h> 

int main() 
{ 
    char * cptr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    short * sptr = (short*)cptr; 
    int * iptr = (int*)cptr; 
    long long * lptr = (long long*)cptr; 

    printf ("CHAR: %d, +1: %d\n",cptr,cptr+1); 
    printf ("SHORT: %d, +1: %d\n",sptr,sptr+1); 
    printf ("INT: %d, +1: %d\n",iptr,iptr+1); 
    printf ("LONG LONG: %d, +1: %d\n",lptr,lptr+1); 
} 

Esto debería:

  • generar advertencias sobre fundición punteros de diferentes tamaños (de seguridad tipo),
  • salida números idénticos en la primera columna (todos los punteros apuntan a la misma dirección en la memoria), pero diferentes números en la segunda columna (que es la dirección base + tamaño del tipo del puntero: 1, 2, 4 y 8 bytes).
13

El compilador necesita saber los tipos apuntados, de lo contrario todo tipo de código no funcionará.Considere lo siguiente:

 
*a = *b + *c; // Should this add char? int? float? 
s_ptr->x = 0; // How does the compiler know anything about the structure s_ptr points to? 
a[5] = 0;  // How far is a[5] from a[0]? 

no tienen tipos de punteros sería como no tener tipos para cualquier cosa. El compilador estaría completamente perdido. En resumen, C y C++ están fuertemente tipados y esto se traslada a punteros por razones bastante obvias.

+0

Err, "fuertemente" mecanografiado significa que el lenguaje no puede hacer un encasillado incoherente. WP: "No permite ningún tipo de conversión de tipo. Los valores de un tipo no se pueden convertir a otro tipo, explícita o implícitamente". http://en.wikipedia.org/wiki/Strongly_typed_programming_language –

+2

Estoy usando una definición más débil como se explica más adelante en la página de wikipedia que enlazas :-) Aunque estoy algo mal. – phkahler

2

En realidad, es el "puntero al vacío" el que debe explicarse.

En los lenguajes de programación en general y en C en particular, nos gustan los tipos. Los tipos son la red de seguridad básica que verifica si estamos haciendo algo estúpido, donde "estúpido" significa "interpretar un montón de bits por algo que no son". Es posible programar sin tipos, algunos idiomas están completamente desprovistos de cualquier tipo de tipo (por ejemplo, montaje o Forth), pero esto no es para cardíacos y, en general, la productividad de los programadores parece mejorarse mucho mediante el uso de tipos .

Por lo tanto, cuando tenemos un puntero queremos que la computadora sepa qué puede encontrar al final del puntero. Queremos un "puntero a int" para que la computadora compruebe que cuando miramos los bits que están al final del puntero, los vemos como un "int" y no como algo más.

El "puntero al vacío" es el puntero sin tipo, que usamos cuando el sistema tipo C no captura lo que estamos haciendo. Es un síntoma de que C no puede seguir la complejidad del código que estamos produciendo (o tal vez el programador no fue lo suficientemente bueno para expresar lo que hace dentro de las limitaciones del sistema tipo C). Por lo tanto, aunque "void *" es conveniente en algunas situaciones, uno debería verlo como la excepción y tratar de evitarlo.

+1

Existe un puntero a void porque no hay un tipo de objeto base. –

+1

@Steven, no, no C no tiene objetos, a veces un blob simplemente no tiene ningún tipo, no es un tipo de base, no es un tipo de objeto/estructura/lo que quieras que quieras llamar, no tipo. El uso de puntero a desconocido es solo uno de sus usos. – wich

+0

@wich: idiomas como C# tienen un tipo de 'objeto 'base, que todas las instancias pueden ser editadas (ya sea Int32 o Employee). Por lo tanto, una referencia '' objeto' de C# cumple la misma función que un puntero 'void' de C++: puede referirse a cualquier cosa. –

0

¿Hay alguna otra razón por la que los punteros que no están vacíos estén presentes en el lenguaje C?

Son una manera increíble de manejar los trozos de memoria libremente. :)

+0

Los tipos de unión son mejores. –

+0

Sí, ¡estoy de acuerdo! :) – SDReyes

2

El tipo de un puntero en C le dice al compilador cuál es el tamaño del bloque de memoria que debe leerse en caso de que intente desreferenciarlo. En otras palabras, al desreferenciar un puntero int, el compilador sabe que se deben leer 4 bytes después de la dirección. Es por eso que se prohíbe la desreferenciación de un puntero vacío sin convertirlo en un puntero tipeado; en este caso, el compilador no sabe cuántos bytes leer después de la dirección.

4

muerto simple:

void* p; 
*p; // compile error! 

O, para decirlo con palabras; un puntero void no puede ser desreferenciado.

Quizás deba cambiar el nombre de la pregunta por qué tenemos punteros, o mejor dicho, no y simplemente busque esa pregunta en SO.

Cuestiones relacionadas