Por ejemplo:
sizeof(char*)
regresa 4. Como no int*
, long long*
todo lo que he probado. ¿Hay alguna excepción a esto?
Por ejemplo:
sizeof(char*)
regresa 4. Como no int*
, long long*
todo lo que he probado. ¿Hay alguna excepción a esto?
Respuestas:
La garantía que obtienes es eso sizeof(char) == 1
. No hay otras garantías, incluida ninguna garantía de eso sizeof(int *) == sizeof(double *)
.
En la práctica, los punteros serán de tamaño 2 en un sistema de 16 bits (si puede encontrar uno), 4 en un sistema de 32 bits y 8 en un sistema de 64 bits, pero no se gana nada confiando en un determinado Talla.
Incluso en una plataforma simple x86 de 32 bits, puede obtener una variedad de tamaños de puntero, pruebe esto por ejemplo:
struct A {};
struct B : virtual public A {};
struct C {};
struct D : public A, public C {};
int main()
{
cout << "A:" << sizeof(void (A::*)()) << endl;
cout << "B:" << sizeof(void (B::*)()) << endl;
cout << "D:" << sizeof(void (D::*)()) << endl;
}
En Visual C ++ 2008, obtengo 4, 12 y 8 para los tamaños de la función de punteros a miembros.
Raymond Chen habló sobre esto aquí .
Solo otra excepción a la lista ya publicada. En plataformas de 32 bits, los punteros pueden tomar 6, no 4 , bytes:
#include <stdio.h>
#include <stdlib.h>
int main() {
char far* ptr; // note that this is a far pointer
printf( "%d\n", sizeof( ptr));
return EXIT_SUCCESS;
}
Si compila este programa con Open Watcom y lo ejecuta, obtendrá 6, porque los punteros lejanos que admite consisten en valores de desplazamiento de 32 bits y segmento de 16 bits
Si está compilando para una máquina de 64 bits, entonces puede ser 8.
sizeof(char*)==1
? ¿Estás seguro? No quiere decir size(char)==1
?
Técnicamente hablando, el estándar C solo garantiza que sizeof (char) == 1, y el resto depende de la implementación. Pero en las arquitecturas modernas x86 (por ejemplo, chips Intel / AMD) es bastante predecible.
Probablemente haya escuchado que los procesadores se describen como de 16 bits, 32 bits, 64 bits, etc. Esto generalmente significa que el procesador usa N bits para enteros. Dado que los punteros almacenan direcciones de memoria y las direcciones de memoria son enteros, esto le indica efectivamente cuántos bits se utilizarán para los punteros. sizeof generalmente se mide en bytes, por lo que el código compilado para procesadores de 32 bits informará que el tamaño de los punteros es de 4 (32 bits / 8 bits por byte), y el código de los procesadores de 64 bits informará que el tamaño de los punteros es de 8 (64 bits / 8 bits por byte). Aquí es de donde proviene la limitación de 4 GB de RAM para procesadores de 32 bits: si cada dirección de memoria corresponde a un byte, para direccionar más memoria necesita enteros mayores de 32 bits.
El tamaño del puntero depende básicamente de la arquitectura del sistema en el que se implementa. Por ejemplo, el tamaño de un puntero en 32 bits es de 4 bytes (32 bits) y 8 bytes (64 bits) en máquinas de 64 bits. Los tipos de bits en una máquina no son más que direcciones de memoria, que pueden tener. Las máquinas de 32 bits pueden tener 2^32
espacio de direcciones y las máquinas de 64 bits pueden tener hasta 2^64
espacios de direcciones. Por lo tanto, un puntero (variable que apunta a una ubicación de memoria) debería poder apuntar a cualquiera de las direcciones de memoria ( 2^32 for 32 bit and 2^64 for 64 bit
) que tiene una máquina.
Por esta razón, vemos que el tamaño de un puntero es de 4 bytes en una máquina de 32 bits y 8 bytes en una máquina de 64 bits.
Además de las diferencias de 16/32/64 bits, pueden ocurrir cosas aún más extrañas.
Ha habido máquinas donde sizeof (int *) será un valor, probablemente 4 pero donde sizeof (char *) es mayor. Las máquinas que naturalmente abordan palabras en lugar de bytes tienen que "aumentar" los punteros de caracteres para especificar qué parte de la palabra realmente desea para implementar correctamente el estándar C / C ++.
Esto es ahora muy inusual ya que los diseñadores de hardware han aprendido el valor de la capacidad de direccionamiento de bytes.
void*
y char*
se manejan en software, y se aumentan con un desplazamiento de 3 bits dentro de la palabra, pero dado que en realidad no hay un espacio de direcciones de 64 bits, el desplazamiento se almacena en los 3 bits de orden superior de los 64 bits palabra. Por lo tanto char*
, y int*
son del mismo tamaño, pero tienen diferentes representaciones internas - y el código que asume que los punteros son "realmente" sólo números enteros pueden dejar mal.
Los punteros de 8 y 16 bits se utilizan en la mayoría de los microcontroladores de bajo perfil. Eso significa que cada lavadora, micro, nevera, televisores antiguos e incluso automóviles.
Se podría decir que no tienen nada que ver con la programación del mundo real. Pero aquí hay un ejemplo del mundo real: Arduino con 1-2-4k ram (dependiendo del chip) con punteros de 2 bytes.
Es reciente, barato, accesible para todos y vale la pena codificarlo.
Además de lo que la gente ha dicho sobre los sistemas de 64 bits (o lo que sea), hay otros tipos de puntero que puntero a objeto.
Un puntero a miembro puede tener casi cualquier tamaño, dependiendo de cómo lo implemente su compilador: ni siquiera son todos del mismo tamaño. Pruebe un puntero a miembro de una clase POD, y luego un puntero a miembro heredado de una de las clases base de una clase con múltiples bases. Qué divertido.
Por lo que recuerdo, se basa en el tamaño de una dirección de memoria. Entonces, en un sistema con un esquema de dirección de 32 bits, sizeof devolverá 4, ya que son 4 bytes.
sizeof (unsigned int) == sizeof (signed int)
, este requisito se encuentra en 3.9.1 / 3. "Para cada uno de la norma entero de tipos, existe un tipo entero sin signo estándar correspondiente (pero diferente): unsigned char
, unsigned short int
, unsigned int
, unsigned long int
, y unsigned long long int
, cada uno de los cuales ocupa la misma cantidad de almacenamiento y tiene los mismos requisitos de alineación como el correspondiente entero de tipo "
En general, el tamaño de (casi cualquier cosa) cambiará cuando compiles en diferentes plataformas. En una plataforma de 32 bits, los punteros son siempre del mismo tamaño. En otras plataformas (64 bits es el ejemplo obvio) esto puede cambiar.
No, el tamaño de un puntero puede variar según la arquitectura. Hay numerosas excepciones.
El tamaño del puntero e int es de 2 bytes en el compilador Turbo C en la máquina con Windows de 32 bits.
Por lo tanto, el tamaño del puntero es específico del compilador. Pero, en general, la mayoría de los compiladores se implementan para admitir variables de puntero de 4 bytes en 32 bits y variables de puntero de 8 bytes en máquinas de 64 bits).
Por lo tanto, el tamaño del puntero no es el mismo en todas las máquinas.
La razón por la que el tamaño de su puntero es de 4 bytes es porque está compilando para una arquitectura de 32 bits. Como señaló FryGuy, en una arquitectura de 64 bits verías 8.
En Win64 (Cygwin GCC 5.4) , veamos el siguiente ejemplo:
Primero, pruebe la siguiente estructura:
struct list_node{
int a;
list_node* prev;
list_node* next;
};
struct test_struc{
char a, b;
};
El código de prueba está abajo:
std::cout<<"sizeof(int): "<<sizeof(int)<<std::endl;
std::cout<<"sizeof(int*): "<<sizeof(int*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(double): "<<sizeof(double)<<std::endl;
std::cout<<"sizeof(double*): "<<sizeof(double*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(list_node): "<<sizeof(list_node)<<std::endl;
std::cout<<"sizeof(list_node*): "<<sizeof(list_node*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(test_struc): "<<sizeof(test_struc)<<std::endl;
std::cout<<"sizeof(test_struc*): "<<sizeof(test_struc*)<<std::endl;
La salida está abajo:
sizeof(int): 4
sizeof(int*): 8
sizeof(double): 8
sizeof(double*): 8
sizeof(list_node): 24
sizeof(list_node*): 8
sizeof(test_struc): 2
sizeof(test_struc*): 8
Puedes ver eso en 64 bits, sizeof(pointer)
es 8
.
Un puntero es solo un contenedor para una dirección. En una máquina de 32 bits, su rango de direcciones es de 32 bits, por lo que un puntero siempre será de 4 bytes. En una máquina de 64 bits donde tiene un rango de direcciones de 64 bits, un puntero será de 8 bytes.
Solo para completar e interés histórico, en el mundo de 64 bits había diferentes convenciones de plataforma sobre los tamaños de tipos largos y largos, llamados LLP64 y LP64, principalmente entre sistemas de tipo Unix y Windows. Un viejo estándar llamado ILP64 también hizo int = 64 bits de ancho.
Microsoft mantuvo LLP64 donde longlong = 64 bit de ancho, pero se mantuvo largo en 32, para facilitar la transferencia.
Type ILP64 LP64 LLP64
char 8 8 8
short 16 16 16
int 64 32 32
long 64 64 32
long long 64 64 64
pointer 64 64 64