tamaño pie pagina modificar letra encabezado como cambiar cabecera c++ c struct packing

c++ - pie - Obtener un tamaño de encabezado diferente al cambiar el tamaño de la ventana



modificar header wordpress (9)

Tengo un programa C ++ que representa un encabezado TCP como una estructura:

#include "stdafx.h" /* TCP HEADER 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Acknowledgment Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data | |U|A|P|R|S|F| | | Offset| Reserved |R|C|S|S|Y|I| Window | | | |G|K|H|T|N|N| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Checksum | Urgent Pointer | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct { // RFC793 WORD wSourcePort; WORD wDestPort; DWORD dwSequence; DWORD dwAcknowledgment; unsigned int byReserved1:4; unsigned int byDataOffset:4; unsigned int fFIN:1; unsigned int fSYN:1; unsigned int fRST:1; unsigned int fPSH:1; unsigned int fACK:1; unsigned int fURG:1; unsigned int byReserved2:2; unsigned short wWindow; WORD wChecksum; WORD wUrgentPointer; } TCP_HEADER, *PTCP_HEADER; int _tmain(int argc, _TCHAR* argv[]) { printf("TCP header length: %d/n", sizeof(TCP_HEADER)); return 0; }

Si ejecuto este programa obtengo el tamaño de este encabezado como 24 bytes, que no es el tamaño que esperaba. Si cambio el tipo del campo "wWindow" a "unsigned int wWindow: 16", que tiene el mismo número de bits que un short sin signo, el programa me dice que el tamaño de la estructura ahora es de 20 bytes, el tamaño correcto. ¿Por qué es esto?

Estoy usando Microsoft Visual Studio 2005 con SP1 en una máquina x86 de 32 bits.


Creo que Mike B lo hizo bien, pero no perfectamente claro. Cuando pides "corto", está alineado en un límite de 32 bits. Cuando pides int: 16, no lo es. Entonces int: 16 se ajusta justo después de los campos de ebit, mientras que el corto omite 2 bytes y comienza en el siguiente bloque de 32 bits.

El resto de lo que dice es perfectamente aplicable: el campo de bits nunca se debe usar para codificar una estructura visible externamente, porque no hay garantía de cómo se asignan. En el mejor de los casos, pertenecen a programas integrados donde guardar un byte es importante. E incluso allí, no puede usarlos para controlar realmente bits en puertos mapeados en memoria.


El compilador está rellenando el miembro de estructura no de bitfield con una alineación de palabra nativa de 32 bits. Para arreglar esto, haga #pragma pack (0) antes de struct y #pragma pack () después.


El compilador puede rellenar los límites de la estructura en la memoria en función del tamaño y el orden de los campos.


Interesante: creo que "WORD" se evaluaría como "short sin firmar", por lo que tendrías ese problema en más de un lugar.

También tenga en cuenta que deberá tratar con problemas endian en cualquier valor de más de 8 bits.


No es un experto en C / C ++ cuando se trata de empacar. Pero imagino que hay una regla en la especificación que dice que cuando un campo no bit sigue a un campo de bits, debe estar alineado en el límite de la palabra, independientemente de si encaja o no en el espacio restante. Al convertirlo en un bitvector explícito, estás evitando este problema.

De nuevo, esto es especulación con un toque de experiencia.


Porque el compilador está empaquetando su bitfield en una int de 32 bits, no en una entidad de 16 bits.

En general, debe evitar los campos de bits y usar otras constantes de manifiesto (enumeraciones o lo que sea) con enmascaramiento y desplazamiento de bits explícitos para acceder a los ''subcampos'' en un campo.

Esta es una de las razones por las que se deben evitar los campos de bits: no son muy portátiles entre los compiladores, incluso para la misma plataforma. del estándar C99 (hay una redacción similar en el estándar C90):

Una implementación puede asignar cualquier unidad de almacenamiento direccionable lo suficientemente grande como para contener un campo de bits. Si queda suficiente espacio, un campo de bits que sigue inmediatamente a otro campo de bits en una estructura debe empaquetarse en los bits adyacentes de la misma unidad. Si queda espacio insuficiente, si un campo de bits que no encaja se coloca en la siguiente unidad o se solapa con las unidades adyacentes, se define la implementación. El orden de asignación de los campos de bits dentro de una unidad (de orden superior a orden inferior o de orden inferior a orden superior) está definido por la implementación. La alineación de la unidad de almacenamiento direccionable no está especificada.

No se puede garantizar si un campo de bit ''abarcará'' un límite int o no y no se puede especificar si un bitfield comienza en el extremo inferior del int o el extremo superior del int (esto es independiente de si el procesador es big-endian o little-endian).


Su serie de campos de bit "unsigned int: xx" usa solo 16 de los 32 bits en un int. Los otros 16 bits (2 bytes) están ahí, pero no utilizados. Esto es seguido por el corto sin firmar, que está en un límite int, y luego un WORD, que está alineado a lo largo de un límite int, lo que significa que hay 2 bytes de relleno entre ellos.

Cuando se cambia a "unsigned int wWindow: 16", en lugar de ser un corto separado, el compilador usa las partes no utilizadas del campo de bits anterior, por lo que no hay desperdicio, ni corto, ni relleno después del corto, por lo tanto, ahorra cuatro bytes.


Está viendo valores diferentes debido a las reglas de empaquetado del compilador. Puedes ver reglas específicas para Visual Studio aquí .

Cuando tiene una estructura que debe empaquetarse (o cumplir con algunos requisitos de alineación específicos), debe usar la opción #pragma pack (). Para su código, puede usar #pragma pack (0) que alineará todos los miembros de la estructura en los límites de bytes. Luego puede usar #pragma pack () para restablecer el empaque de la estructura a su estado predeterminado. Puede ver más información sobre el paquete pragma aquí .