Si tenemos que mantener una dirección de cualquier tipo de datos, entonces necesitamos el puntero de ese tipo de datos. Pero un puntero es simplemente una dirección, y una dirección es siempre int
tipo, entonces ¿por qué la dirección de retención de cualquier tipo de datos requiere el puntero de ese tipo?¿Por qué diferentes tipos de puntero para diferentes tipos de datos en c?
Respuesta
Hay varias razones:
- No todas las direcciones son creados iguales; En particular, en las arquitecturas no Von Neuman (por ejemplo, Harvard) punteros a la memoria de código (donde a menudo se almacenan constantes) y punteros a la memoria de datos son diferentes.
- Necesita conocer el tipo subyacente para realizar sus accesos correctamente. Por ejemplo, leer o escribir un
char
es diferente de leer o escribir undouble
. - Necesita información adicional para realizar la aritmética del puntero.
Tenga en cuenta que hay un tipo de puntero que significa "simplemente un puntero" en C, llamado void*
. Puede usar este puntero para transferir una dirección en la memoria, pero debe convertirla en algo útil para realizar operaciones en la memoria apuntada por void*
.
Porque su suposición de que "la dirección siempre es de tipo int" es incorrecta.
Es posible crear una arquitectura de computadora donde, por ejemplo, los punteros a los caracteres son más grandes que los punteros a las palabras, por alguna razón. C se encargará de esto.
Además, por supuesto, los indicadores pueden ser desreferenciados y cuando lo hace, el compilador necesita saber el tipo de datos que espera encontrar en la dirección en cuestión. De lo contrario, no puede generar las instrucciones adecuadas para tratar con esos datos.
considerar:
char *x = malloc(sizeof *x);
*x = 0;
double *y = malloc(sizeof *y);
*y = 0;
Estos dos fragmentos escribirán totalmente diferentes cantidades de memoria (o estallar si las asignaciones fallan, no importa que, por ahora), pero la constante literal real (0
que es de tipo int
) es lo mismo en ambos casos. La información sobre los tipos de punteros permite al compilador generar el código correcto.
Además de eso, las matemáticas de puntero dependen del tipo de punta. – DCoder
Bueno, "es totalmente posible crear una arquitectura de computadora donde ..." es una tierra peligrosa para explorar. De hecho, también es posible crear uno en el que un programa escrito en C no funcione a menos que utilice algún tipo de simulador muy lento (simplemente no admitiendo la arquitectura de memoria dictada por C). –
Puede tener un puntero sin letra en C muy fácilmente: solo usa void *
para todos los punteros. Sin embargo, esto sería bastante tonto por dos razones que se me ocurren.
Primero, al especificar los datos que se apuntan en el tipo, el compilador lo salva de muchos errores tontos, errores tipográficos u otros. Si, en cambio, privas al compilador de esta información, estás obligado a pasar MUCHO tiempo depurando cosas que nunca deberían haber sido un problema.
Además, probablemente haya usado "aritmética del puntero". Por ejemplo, int *pInt = &someInt; pInt++;
- que avanza el puntero al siguiente entero en la memoria; esto funciona independientemente del tipo, y avanza a la dirección correcta, pero solo puede funcionar si el compilador conoce el tamaño de lo que se está apuntando.
Es principalmente para aquellos que leen el código después de usted para que puedan saber qué se almacena en esa dirección.Además, si hace aritmética de puntero en su código, el compilador necesita saber cuánto se supone que debe avanzar si hace algo como pSomething ++, que viene dado por el tipo del puntero, ya que el tamaño de su tipo de datos es conocido antes de la compilación.
Porque El tipo de puntero indica al compilador que a la vez en cuántos bytes puede realizar la operación.
Ejemplo: - en el caso de char solo 1 byte
Y puede estar en diferente en caso de int 2 byte.
Los apuntadores no son solo int
. Ellos implícitamente tienen semántica.
Aquí hay un par de ejemplos:
p->member
sólo tiene sentido si se sabe qué tipop
puntos a.p = p+1;
se comporta de manera diferente según el tamaño del objeto al que apunta (en el sentido de que 'p' de hecho se incrementa, cuando se ve como un entero sin signo, por el tamaño del tipo al que apunta).
El siguiente ejemplo puede ayudar a entender las diferencias entre los punteros de diferentes tipos:
#include <stdio.h>
int main()
{
// pointer to char
char * cp = "Abcdefghijk";
// pinter to int
int * ip = (int *)cp; // to the same address
// try address arithmetic
printf("Test of char*:\n");
printf("address %p contains data %c\n", cp, *cp);
printf("address %p contains data %c\n", (cp+1), *(cp+1));
printf("Test of int*:\n");
printf("address %p contains data %c\n", ip, *ip);
printf("address %p contains data %c\n", (ip + 1), *(ip + 1));
return 0;
}
la salida se
es importante entender que address+1
expresión da diferente resultado dependiendo del tipo address
, es decir, +1
significa sizeof(addressed data)
, como sizeof(*address)
.
lo tanto, si en el sistema (por su compilador) sizeof(int)
y sizeof(char)
son diferentes (por ejemplo, 4 y 1), los resultados de cp+1
y ip+1
también es diferente. En mi sistema es:
E05859(hex) - E05858(hex) = 14702684(dec) - 14702681(dec) = 1 byte for char
E0585C(hex) - E05858(hex) = 14702684(dec) - 14702680(dec) = 4 bytes for int
Nota: los valores de dirección específicos no son importantes en este caso, la única diferencia es importante.
Actualización:
Por la dirección de forma (puntero) la aritmética no está limitada por +1
o ++
, tantos ejemplos se pueden hacer, como:
int arr[] = { 1, 2, 3, 4, 5, 6 };
int *p1 = &arr[1];
int *p4 = &arr[4];
printf("Distance between %d and %d is %d\n", *p1, *p4, p4 - p1);
printf("But addresses are %p and %p have absolute difference in %d\n", p1, p4, int(p4) - int(p1));
con la salida
Por lo tanto, para una mejor comprensión, lea the tutorial
- 1. ¿Lista de diferentes tipos?
- 2. ¿Cómo almacenar diferentes tipos de datos en una lista? (C++)
- 3. matriz bidimensional de diferentes tipos
- 4. ¿Por qué el método Arrays.sort de Java utiliza dos algoritmos de clasificación diferentes para diferentes tipos?
- 5. Terminología para diferentes tipos de funciones
- 6. Enumeración rápida en NSArray de diferentes tipos
- 7. set_intersection para dos tipos diferentes de conjuntos
- 8. ¿Para qué sirven los diferentes tipos de muestras HLSL?
- 9. Diferentes tipos de aplicaciones de Xcode
- 10. Lista de listas de diferentes tipos
- 11. Índice de MongoDB en diferentes tipos
- 12. xsd mismo elemento, ¿diferentes tipos?
- 13. Obtener/establecer como tipos diferentes
- 14. ¿Almacena diferentes tipos de datos en una matriz NumPy?
- 15. Diferentes tipos de continuación en raqueta
- 16. ¿Cómo diferencia Python entre los diferentes tipos de datos?
- 17. Definición de diferentes tipos de números en C#
- 18. Convertir diccionario genérico para diferentes tipos
- 19. Uso de diferentes tipos de variables numéricas
- 20. Django - Perfiles de usuario de diferentes tipos
- 21. Cuentas de modelado para diferentes tipos de usuarios en Django
- 22. ¿Diferentes tipos de índices de base de datos?
- 23. ¿Almacena diferentes tipos dentro de una lista?
- 24. Crear diferentes tipos de distribución con setup.py
- 25. jQuery AJAX y manejo de diferentes tipos de datos
- 26. interfaces separadas 'admin' para diferentes tipos de usuario en django
- 27. ¿Qué tipos de datos de C# pueden ser tipos anulables?
- 28. Orden por y Diferentes tipos en un CASO
- 29. SQLAlchemy sinónimo columna con diferentes tipos
- 30. OCaml tipos con diferentes niveles de especificidad
Hay más información en el puntero (desde la vista de C) que en su dirección. También está el tipo. Si su puntero no tenía un tipo, ¿qué significaría desreferenciarlo? – nos
Consulte también [¿Por qué los punteros a las funciones y los punteros de datos son incompatibles en C/C++] (http: // stackoverflow.com/questions/12358843/why-are-function-punteros-and-data-punteros-incompatible-en-cc) –
Si escribe en BCPL y B (predecesores de C) o en ensamblado, tendrá eso, punteros = entero números. En C, los indicadores están cargados: están diseñados para señalar cosas de tamaños posiblemente diferentes, posiblemente ubicadas en diferentes memorias. Y desreferenciar tales punteros no se puede implementar si los punteros son solo enteros rectos y nada más (bajo el capó todavía son enteros, sin embargo, eso es solo cuando el compilador se ha ocupado de toda la información de tipo y tamaño). –