Consider I have Struct like the following:
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;
I am initializing it with appropriate values. Finally, I want to convert the struct into char* so I can append my payload (which is char* message) and send it over a websocket connection.
In C, we can get the memory address of any variable or member field (of struct). To do so, we use the address of (&) operator, the %p specifier to print it and a casting of (void*) on the address.
Structures (also called structs) are a way to group several related variables into one place. Each variable in the structure is known as a member of the structure. Unlike an array, a structure can contain many different data types (int, float, char, etc.).
Is a struct's address the same as its first member's address?
Yes, this is actually mandated by the C and C++ standards. From the C standard:
6.7.2.1-13. A pointer to a structure object, suitably converted, points to its initial member
The size of your struct
should be two bytes. You should not convert a pointer to it to char*
, though: instead, you should use memcpy
to copy your Bitmask
into the buffer that you send over the network.
EDIT Since you use scatter-gather I/O with iovec
, you do not need to cast Bitmask
to anything: iov_base
is void*
, so you can simply set iov[0].iov_base = header;
Note: This works only as long as your struct
does not contain virtual functions, base classes, etc. (thanks, Timo).
EDIT2
In order to get {0x81, 0x05} in your struct
, you should change the order of structure elements as follows:
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;
}
Yes and no.
In general, this is true (as dasblinkenlight explains), but it specifically doesn't hold for bitfields. Per C++11 9.6/3 "there are no pointers to bitfields" so they don't have addresses, either. And obviously, "A pointer to a structure object, suitably converted, points to its initial member" breaks down if there is no "suitable conversion".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With