variable una tamaño saber qué length hace funcion como array c++ c++11 sizeof alignof

c++ - una - sizeof ansi c



¿Cuál es la diferencia entre sizeof y alignof? (6)

Bueno, la "memoria" es básicamente una gran variedad de bytes. Sin embargo, la mayoría de las cosas más grandes, como los enteros, necesitan más de 1 byte para almacenarlas: un valor de 32 bits, por ejemplo, usaría 4 bytes consecutivos de memoria.

Ahora, los módulos de memoria en su computadora generalmente no son "bytes"; también están organizados con unos pocos bytes "en paralelo", como bloques de 4 bytes.

Para una CPU, es mucho más fácil = más eficiente = mejor rendimiento para no "cruzar" dichos bordes de bloques cuando se lee algo así como un entero:

memory byte 0 1 2 3 4 5 6 7 8 9 10 11 integer goooood baaaaaaaaad

Esto es lo que dice la "alineación": una alineación de 4 significa que los datos de este tipo deben (o deben, depende de la CPU) almacenarse comenzando en una dirección que es un múltiplo de 4.

Observa que el tamaño de == alignof es incorrecto; probar estructuras. Las estructuras también estarán alineadas (porque sus miembros individuales deben terminar en las direcciones correctas), pero su tamaño será mucho mayor.

¿Cuál es la diferencia entre sizeof y alignof?

#include <iostream> #define SIZEOF_ALIGNOF(T) std::cout<< sizeof(T) << ''/'' << alignof(T) << std::endl int main(int, char**) { SIZEOF_ALIGNOF(unsigned char); SIZEOF_ALIGNOF(char); SIZEOF_ALIGNOF(unsigned short int); SIZEOF_ALIGNOF(short int); SIZEOF_ALIGNOF(unsigned int); SIZEOF_ALIGNOF(int); SIZEOF_ALIGNOF(float); SIZEOF_ALIGNOF(unsigned long int); SIZEOF_ALIGNOF(long int); SIZEOF_ALIGNOF(unsigned long long int); SIZEOF_ALIGNOF(long long int); SIZEOF_ALIGNOF(double); }

saldrá

1/1 1/1 2/2 2/2 4/4 4/4 4/4 4/4 4/4 8/8 8/8 8/8

Creo que no entiendo cuál es la alineación ...



El valor de alignof es el mismo que el valor de sizeof para los tipos básicos.

La diferencia radica en los tipos de datos definidos utilizados, como el uso de struct; por ejemplo,

typedef struct { int a; double b; } S; //cout<<alignof(s); outputp: 8; //cout<<sizeof(S); output: 12;

por lo tanto, el tamaño del valor es el tamaño total requerido para el tipo de datos dado; y el valor de alignof es el requisito de alineación del elemento más grande en la estructura.

Uso de alignof: asigna memoria en un límite de alineación particular.


Los dos operadores hacen cosas fundamentalmente diferentes. sizeof da el tamaño de un tipo (cuánta memoria toma) mientras que alignof da qué cantidad de bytes debe estar alineado con un tipo. Sucede que las primitivas que has probado tienen un requisito de alineación igual al tamaño (lo que tiene sentido si lo piensas).

Piense en lo que sucede si tiene una estructura en su lugar:

struct Foo { int a; float b; char c; };

alignof(Foo) devolverá 4.


Para las respuestas proporcionadas, parece haber cierta confusión acerca de qué alineación realmente es. La confusión probablemente surge porque hay 2 tipos de alineación.

1. Alineación de miembros

Esta es una medida cualitativa que explica qué tan grande es una instancia en número de bytes para un orden específico de los miembros dentro del tipo de estructura / clase. En general, los compiladores pueden compactar las instancias de estructura / clase si los miembros se ordenan por su tamaño de byte en orden descendente (es decir, el más grande primero, el último miembro más pequeño) dentro de la estructura. Considerar:

struct A { char c; float f; short s; }; struct B { float f; short s; char c; };

Ambas estructuras contienen exactamente la misma información. Por el bien de este ejemplo; el tipo de letra flotante toma 4 bytes, el tipo abreviado toma 2 y el carácter toma 1 byte. Sin embargo, la primera estructura A tiene miembros en orden aleatorio, mientras que la segunda estructura B ordena miembros de acuerdo con su tamaño de byte (esto puede ser diferente en ciertas arquitecturas, supongo que la arquitectura de CPU intel x86 con alineación de 4 bytes en este ejemplo). Ahora considere el tamaño de las estructuras:

printf("size of A: %d", sizeof (A)); // size of A: 12; printf("size of B: %d", sizeof (B)); // size of B: 8;

Si espera que el tamaño sea de 7 bytes, supondría que los miembros están empaquetados en la estructura con una alineación de 1 byte. Mientras que algunos compiladores lo permiten, en general la mayoría de los compiladores usan alineaciones de 4 bytes o incluso de 8 bytes debido a razones históricas (la mayoría de las CPU trabajan con registros de propósito general DWORD (palabra doble) o QWORD (palabra cuádruple).

Hay 2 mecanismos de relleno en funcionamiento para lograr el empaque.

  1. En primer lugar, cada miembro que tenga un tamaño de byte más pequeño que la alineación de bytes se ''fusiona'' con el siguiente miembro (s) si el tamaño de byte resultante es menor o igual que el byte-alignment. En la estructura B, los miembros s y c se pueden combinar de esta manera; su tamaño combinado es de 2 bytes para s + 1 byte para c == 3 bytes <= alineación de 4 bytes. Para la estructura A, no puede ocurrir tal fusión, y cada miembro consume efectivamente 4 bytes en el empaque de la estructura.

  2. El tamaño total de la estructura vuelve a estar acolchado para que la siguiente estructura pueda comenzar en el límite de alineación. En el ejemplo B, el número total de bytes sería 7. El siguiente límite de 4 bytes se encuentra en el byte 8, por lo tanto, la estructura se rellena con 1 byte para permitir asignaciones de matriz como una secuencia ajustada de instancias.

Tenga en cuenta que Visual C ++ / GCC permite diferentes alineamientos de 1 byte, 2 y múltiplos superiores de 2 bytes. Comprenda que esto funciona en contra de la capacidad de su compilador de producir código óptimo para su arquitectura. De hecho, en el siguiente ejemplo, cada byte se leería como un solo byte usando una instrucción de un solo byte para cada operación de lectura. En la práctica, el hardware aún buscará toda la línea de memoria que contiene cada byte leído en la caché, y ejecutará la instrucción 4 veces, incluso si los 4 bytes están en el mismo DWORD y podrían cargarse en el registro de la CPU en 1 instrucción.

#pragma pack(push,1) struct Bad { char a,b,c,d; }; #pragma pack(pop)

2. Alineación de asignación

Esto está estrechamente relacionado con el segundo mecanismo de relleno explicado en la sección anterior, sin embargo, las alineaciones de asignación pueden especificarse en variantes de funciones de asignación malloc / memalloc , por ejemplo, calloc . Por lo tanto, es posible asignar un objeto a un límite de alineación diferente (típicamente un múltiplo más alto de 2) de lo que sugiere la alineación de bytes del tipo de estructura / objeto.

size_t blockAlignment = 4*1024; // 4K page block alignment void* block = calloc(sizeof(T) * count, blockAlignment);

El código colocará el bloque de instancias de conteo de tipo T en las direcciones que terminan en múltiplos de 4096.

La razón para usar tales alineaciones de asignación es nuevamente puramente arquitectónica. Por ejemplo, leer y escribir bloques desde direcciones alineadas a la página es más rápido porque el rango de direcciones encaja muy bien en las capas de la memoria caché. Los rangos que se dividen en diferentes "páginas" trash la memoria caché al cruzar el límite de la página. Los diferentes medios (arquitecturas de bus) tienen diferentes patrones de acceso y pueden beneficiarse de diferentes alineamientos. Generalmente, las alineaciones de tamaños de página 4, 16, 32 y 64 K no son infrecuentes.


Una pregunta anterior (aunque no se marcó como respondida ...) pero pensé que este ejemplo hace la diferencia un poco más explícita además de la respuesta de Christian Stieber. Además, la respuesta de Meluha contiene un error ya que el tamaño de la (S) salida es 16, no 12.

// c has to occupy 8 bytes so that d (whose size is 8) starts on a 8 bytes boundary // | 8 bytes | | 8 bytes | | 8 bytes | struct Bad { char c; double d; int i; }; cout << alignof(Bad) << " " << sizeof(Bad) << endl; // 8 24 // | 8 bytes | | 8 bytes | struct Good { double d; int i; char c; }; cout << alignof(Good) << " " << sizeof(Good) << endl; // 8 16

También demuestra que es mejor ordenar a los miembros por tamaño con el primero más grande (el doble en este caso), ya que los demás miembros están limitados por ese miembro.