Consider the following code:
// First, we get the C-string (NULL-terminated array of bytes) out of NSString.
const char *cString = [command UTF8String];
// The length of C-string (a number of bytes!) differs terribly from
// NSString length (number of characters! Unicode characters are
// of variable length!).
// So we get actual number of bytes and clamp it to the buffer
// size (so if the command string occasionally gets larger than our
// buffer, it gets truncated).
size_t byteCount = MIN(BUFFER_SIZE - 4,
[command lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
// Now we're using C type conversion to reinterpret the buffer as a
// pointer to int32_t. The buffer points to some memory, it's up to us
// how to treat it.
*(int32_t *)buffer = byteCount;
// And finally we're copying our string bytes to the rest of the buffer.
memcpy(buffer + 4, cString, byteCount);
There's a caveat in this code - it uses host byte order to store uint32_t
variable, so if you're passing this buffer over network, it's generally a good idea to make your byte order fixed (networking historically employs big-endianness, though most of the computers are nowadays little-endian).
To fix the byte order just replace the line
*(int32_t *)buffer = byteCount;
with
*(int32_t *)buffer = htonl(byteCount);
And don't forget to convert byte ordering back when processing this buffer on other computer!