2012-02-13 20 views
6

Considere tengo Struct como la siguiente:¿La dirección de una estructura es la misma que la de su primer miembro?

struct Bitmask 
{ 
    unsigned char payload_length: 7; 
    unsigned char mask: 1; 
    unsigned char opcode: 4; 
    unsigned char rsv3: 1; 
    unsigned char rsv2: 1; 
    unsigned char rsv1: 1; 
    unsigned char fin: 1; 
}; 

const char* payload = "Hello"; 
const size_t payload_length = strlen(payload); 

Bitmask* header = new Bitmask(); 
header->fin =1; 
header->rsv1 = 0; 
header->rsv2 = 0; 
header->rsv3 = 0; 
header->opcode = 1; 
header->mask = 0; 
header->payload_length = payload_length; 

iovec iov[2]; 
iov[0].iov_base = (char*)header; 
iov[0].iov_len = sizeof (header); 
iov[1].iov_base = (char *)payload; 
iov[1].iov_len = strlen(payload); 

ACE_DEBUG ((LM_DEBUG, 
      ACE_TEXT ("iov[0].length = %d\niov[1].length = %d\n"), 
      iov[0].iov_len, 
      iov[1].iov_len)); 

size_t bytes_xfered; 
client_stream_.sendv_n (iov, 2, 0, &bytes_xfered); 

cout << "Transfered " << bytes_xfered << " byte(s)" << std::endl; 

Estoy inicializarlo con los valores apropiados. Finalmente, quiero convertir la estructura en char * para poder agregar mi carga útil (que es un mensaje char *) y enviarla a través de una conexión websocket.

Respuesta

14

¿La dirección de una estructura es la misma que la de su primer miembro?

Sí, esto es realmente obligatorio por los estándares C y C++. Desde el estándar C:

6.7.2.1-13. Un puntero a un objeto de estructura, convenientemente convertido, apunta a su miembro inicial

El tamaño de su struct debe ser de dos bytes. Sin embargo, no debe convertir un puntero a char*: en su lugar, debe usar memcpy para copiar su Bitmask en el búfer que envía a través de la red.

EDITAR Puesto que se utiliza dispersión de reunir I/O con iovec, que no es necesario emitir Bitmask a cualquier cosa: iov_base es void*, por lo que simplemente puede establecer iov[0].iov_base = header;

Nota: Esto funciona sólo mientras como su struct no contiene funciones virtuales, clases base, etc. (gracias, Timo).

Edit2

el fin de obtener {0x81, 0x05} en su struct, debe cambiar el orden de los elementos de la estructura de la siguiente manera:

struct Bitmask { 
    unsigned char opcode: 4; 
    unsigned char rsv3: 1; 
    unsigned char rsv2: 1; 
    unsigned char rsv1: 1; 
    unsigned char fin: 1; 
    unsigned char payload_length: 7; 
    unsigned char mask: 1; 
} 
+7

En C++ esto solo se aplica a las estructuras POD. – Timo

+0

¿Debo copiar el miembro de Bitmask por miembro o lo haré? char header_ [2]; memcpy (header_, bitmask, 2); –

+0

@DarshanPuranik No me di cuenta de que estaba usando la E/S scatter-gather. Ver mi edición – dasblinkenlight

1

Sí y no.

En general, esto es cierto (como explica dasblinkenlight), pero específicamente no es válido para los campos de bits. Por C++ 11 9.6/3 "no hay punteros a los campos de bits" por lo que tampoco tienen direcciones. Y obviamente, "Un puntero a un objeto de estructura, adecuadamente convertido, apunta a su miembro inicial" se rompe si no hay "conversión adecuada".

1

La dirección de una estructura es la misma que la dirección de su primer miembro, siempre que se use el modelo apropiado. Dada la siguiente declaración de struct my_struct, si el elemento es del tipo struct

my_struct, then (char *) item == & item.wp_cval.

struct my_struct {

char wp_cval; 
    short wp_font; 
    short wp_psize; 

} ar [ARSIZE];

Cuestiones relacionadas