I have to memset 4 bytes in a char
* with an integer.
For exemple I have an integer int i = 3276854 (0x00320036)
and a char header[54] = {0}
. I have to write i at header + 2, as if I print memory from header[2] to header[6], I get :
0032 0036
I tried this:
memset(&header[2], i, 1);
But it seems to put only the last byte into header, I get :
0036 0000
I also tried:
memset(&header[2], i, 4);
But it fill each byte with the last byte of i, I get :
3636 3636
I also tried to use binary masks like that :
ft_memset(&header[2], (int)(54 + size) & 0xff000000, 1);
ft_memset(&header[3], (int)(54 + size) & 0x00ff0000, 1);
ft_memset(&header[4], (int)(54 + size) & 0x0000ff00, 1);
ft_memset(&header[5], (int)(54 + size) & 0x000000ff, 1);
I get :
3600 0000.
So I don't know how I can get my 0032 0036
, or at least 3600 3200
(maybe there is a thing with little and big endian into that, because I run it under MacOS, which is big endian).
memset
fills memory with a constant byte value. The second parameter (of type int
) is converted to an unsigned char
value.
You could use memcpy
like this:
memcpy(&header[2], &i, sizeof(i));
However, it depends what exactly you are trying to achieve. If the header needs the integer to be in a particular format, you may need to convert the value in some way. For example, if the value needs to be big-endian (which is also known as "network byte order" in several Internet protocols), you can convert it with the htonl
function:
uint32_t bi = htonl(i);
memcpy(&header[2], &bi, sizeof(bi));
(The htonl
function is defined by #include <arpa/inet.h>
.)
Also check the newer byte order conversion functions htobe16
, htole16
, be16toh
, le16toh
, htobe32
, htole32
, be32toh
, le32toh
, htobe64
, htole64
, be64toh
, and le64toh
declared by:
#define _BSD_SOURCE
#include <endian.h>
These convert between host byte order and little-endian byte order, or between host byte order and big-endian byte order, and work on uint16_t
, uint32_t
or uint64_t
values, depending on the function name.
If there are no equivalents to those byte-order conversion functions provided on your system the following non-optimized, but portable (on implementations that support uint16_t
, uint32_t
and uint64_t
) functions may be used:
myendian.h
#ifndef MYENDIAN_H__INCLUDED_
#define MYENDIAN_H__INCLUDED_
#include <stdint.h>
uint16_t my_htobe16(uint16_t h16);
uint16_t my_htole16(uint16_t h16);
uint16_t my_be16toh(uint16_t be16);
uint16_t my_le16toh(uint16_t le16);
uint32_t my_htobe32(uint32_t h32);
uint32_t my_htole32(uint32_t h32);
uint32_t my_be32toh(uint32_t be32);
uint32_t my_le32toh(uint32_t le32);
uint64_t my_htobe64(uint64_t h64);
uint64_t my_htole64(uint64_t h64);
uint64_t my_be64toh(uint64_t be64);
uint64_t my_le64toh(uint64_t le64);
#endif
myendian.c
#include "myendian.h"
union swab16
{
uint16_t v;
uint8_t b[2];
};
union swab32
{
uint32_t v;
uint8_t b[4];
};
union swab64
{
uint64_t v;
uint8_t b[8];
};
static uint16_t xbe16(uint16_t x)
{
union swab16 s;
s.b[0] = (x >> 8) & 0xffu;
s.b[1] = x & 0xffu;
return s.v;
}
static uint16_t xle16(uint16_t x)
{
union swab16 s;
s.b[0] = x & 0xffu;
s.b[1] = (x >> 8) & 0xffu;
return s.v;
}
static uint32_t xbe32(uint32_t x)
{
union swab32 s;
s.b[0] = (x >> 24) & 0xffu;
s.b[1] = (x >> 16) & 0xffu;
s.b[2] = (x >> 8) & 0xffu;
s.b[3] = x & 0xffu;
return s.v;
}
static uint32_t xle32(uint32_t x)
{
union swab32 s;
s.b[0] = x & 0xffu;
s.b[1] = (x >> 8) & 0xffu;
s.b[2] = (x >> 16) & 0xffu;
s.b[3] = (x >> 24) & 0xffu;
return s.v;
}
static uint64_t xbe64(uint64_t x)
{
union swab64 s;
s.b[0] = (x >> 56) & 0xffu;
s.b[1] = (x >> 48) & 0xffu;
s.b[2] = (x >> 40) & 0xffu;
s.b[3] = (x >> 32) & 0xffu;
s.b[4] = (x >> 24) & 0xffu;
s.b[5] = (x >> 16) & 0xffu;
s.b[6] = (x >> 8) & 0xffu;
s.b[7] = x & 0xffu;
return s.v;
}
static uint64_t xle64(uint64_t x)
{
union swab64 s;
s.b[0] = x & 0xffu;
s.b[1] = (x >> 8) & 0xffu;
s.b[2] = (x >> 16) & 0xffu;
s.b[3] = (x >> 24) & 0xffu;
s.b[4] = (x >> 32) & 0xffu;
s.b[5] = (x >> 40) & 0xffu;
s.b[6] = (x >> 48) & 0xffu;
s.b[7] = (x >> 56) & 0xffu;
return s.v;
}
uint16_t my_htobe16(uint16_t h16)
{
return xbe16(h16);
}
uint16_t my_htole16(uint16_t h16)
{
return xle16(h16);
}
uint16_t my_be16toh(uint16_t be16)
{
return xbe16(be16);
}
uint16_t my_le16toh(uint16_t le16)
{
return xle16(le16);
}
uint32_t my_htobe32(uint32_t h32)
{
return xbe32(h32);
}
uint32_t my_htole32(uint32_t h32)
{
return xle32(h32);
}
uint32_t my_be32toh(uint32_t be32)
{
return xbe32(be32);
}
uint32_t my_le32toh(uint32_t le32)
{
return xle32(le32);
}
uint64_t my_htobe64(uint64_t h64)
{
return xbe64(h64);
}
uint64_t my_htole64(uint64_t h64)
{
return xle64(h64);
}
uint64_t my_be64toh(uint64_t be64)
{
return xbe64(be64);
}
uint64_t my_le64toh(uint64_t le64)
{
return xle64(le64);
}
Test harness: myendiantest.c
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include "myendian.h"
#define TEST(n, fn, v) \
printf("%s(%#" PRIx##n ") = %#" PRIx##n "\n", #fn, (v), (fn)(v))
int main(void)
{
const uint16_t t16 = UINT16_C(0x1234);
const uint32_t t32 = UINT32_C(0x12345678);
const uint64_t t64 = UINT64_C(0x123456789abcdef);
TEST(16, my_htobe16, t16);
TEST(16, my_htole16, t16);
TEST(16, my_be16toh, t16);
TEST(16, my_le16toh, t16);
TEST(32, my_htobe32, t32);
TEST(32, my_htole32, t32);
TEST(32, my_be32toh, t32);
TEST(32, my_le32toh, t32);
TEST(64, my_htobe64, t64);
TEST(64, my_htole64, t64);
TEST(64, my_be64toh, t64);
TEST(64, my_le64toh, t64);
return 0;
}
Output on a little endian system:
my_htobe16(0x1234) = 0x3412
my_htole16(0x1234) = 0x1234
my_be16toh(0x1234) = 0x3412
my_le16toh(0x1234) = 0x1234
my_htobe32(0x12345678) = 0x78563412
my_htole32(0x12345678) = 0x12345678
my_be32toh(0x12345678) = 0x78563412
my_le32toh(0x12345678) = 0x12345678
my_htobe64(0x123456789abcdef) = 0xefcdab8967452301
my_htole64(0x123456789abcdef) = 0x123456789abcdef
my_be64toh(0x123456789abcdef) = 0xefcdab8967452301
my_le64toh(0x123456789abcdef) = 0x123456789abcdef
Output on a big endian system (expected, but not tested by me):
my_htobe16(0x1234) = 0x1234
my_htole16(0x1234) = 0x3412
my_be16toh(0x1234) = 0x1234
my_le16toh(0x1234) = 0x3412
my_htobe32(0x12345678) = 0x12345678
my_htole32(0x12345678) = 0x78563412
my_be32toh(0x12345678) = 0x12345678
my_le32toh(0x12345678) = 0x78563412
my_htobe64(0x123456789abcdef) = 0x123456789abcdef
my_htole64(0x123456789abcdef) = 0xefcdab8967452301
my_be64toh(0x123456789abcdef) = 0x123456789abcdef
my_le64toh(0x123456789abcdef) = 0xefcdab8967452301