Convert Integer to Array of UInt8 Units

Convert integer to array of UInt8 units

It seems that what you are looking for is an array with the ASCII
codes of the (decimal) string representation of the number:

let x = 94887253
let a = Array(String(x).utf8)

print(a == [0x39, 0x34, 0x38, 0x38, 0x37, 0x32, 0x35, 0x33]) // true

Convert Int to Array of UInt8 in swift

You could do it this way:

let x: Int = 2019
let length: Int = 2 * MemoryLayout<UInt8>.size //You could specify the desired length

let a = withUnsafeBytes(of: x) { bytes in
Array(bytes.prefix(length))
}

let result = Array(a.reversed()) //[7, 227]

Or more generally, we could use a modified version of this snippet:

func bytes<U: FixedWidthInteger,V: FixedWidthInteger>(
of value : U,
to type : V.Type,
droppingZeros: Bool
) -> [V]{

let sizeInput = MemoryLayout<U>.size
let sizeOutput = MemoryLayout<V>.size

precondition(sizeInput >= sizeOutput, "The input memory size should be greater than the output memory size")

var value = value
let a = withUnsafePointer(to: &value, {
$0.withMemoryRebound(
to: V.self,
capacity: sizeInput,
{
Array(UnsafeBufferPointer(start: $0, count: sizeInput/sizeOutput))
})
})

let lastNonZeroIndex =
(droppingZeros ? a.lastIndex { $0 != 0 } : a.indices.last) ?? a.startIndex

return Array(a[...lastNonZeroIndex].reversed())
}

let x: Int = 2019
bytes(of: x, to: UInt8.self, droppingZeros: true) // [7, 227]
bytes(of: x, to: UInt8.self, droppingZeros: false) // [0, 0, 0, 0, 0, 0, 7, 227]

Converting a UINT16 value into a UINT8 array[2]

How about

UINT16 value = 0xAAFF;
UINT8 array[2];
array[0]=value & 0xff;
array[1]=(value >> 8);

This should deliver the same result independent of endianness.

Or, if you want to use an array initializer:

UINT8 array[2]={ value & 0xff, value >> 8 };

(However, this is only possible if value is a constant.)

How to convert a struct varible to uint8_t array in C

Answer 1/3: use a union and a packed struct

See also my much longer answer here: Portability of using union for conversion

You can do the conversion to a byte array using a union. Be sure to pack the struct to remove padding bytes.

typedef struct __attribute__ ((__packed__)) message_s
{
uint16_t time;
uint16_t lat;
uint8_t ns;
uint16_t lon;
uint8_t ew;
} message_t;

typedef union message_converter_u
{
message_t message;
uint8_t bytes[sizeof(message_t)];
} message_converter_t;

Now do the conversion through the message_converter_t union:

message_t message =
{
.time = 0x1234,
.lat = 0x2122,
.ns = 'n', // 0x6E
.lon = 0x1834,
.ew = 'e', // 0x65
};

message_converter_t converter;
converter.message = message;

That's it!

converter.bytes is now magically a uint8_t array with 8 elements containing all the bytes of the struct.

It has endianness considerations, however!

Note: copying message into converter.message above is unnecessarily inefficient, since it's an unnecessary byte-for-byte copy of the whole message struct. A more-efficient way is to simply construct the union type alone and populate the struct data inside the union directly. See "struct_to_array_via_type_punning_union_more_efficient.c" below for that demo.

Here is some sample print code to print all the bytes:

// Print the bytes
printf("bytes = [");
for (size_t i = 0; i < sizeof(converter.bytes); i++)
{
printf("0x%02X", converter.bytes[i]);
if (i < sizeof(converter.bytes) - 1)
{
printf(", ");
}
}
printf("]\n");

and the output on a 64-bit little-endian x86-architecture Linux machine:

bytes = [0x34, 0x12, 0x22, 0x21, 0x6E, 0x34, 0x18, 0x65]

Notice that due to my machine being little-endian, the least-significant-byte 0x34 comes first in the time variable of 0x1234. So, you get 0x34 and then 0x12. This happens with all of the multi-byte variables. To remove endianness considerations across hardware architectures, you'd have to move to a bit-shifting approach instead of using a union--see my link above for examples and more details, and also see my Answer 2/3 here.



Full, runnable example

struct_to_array_via_type_punning_union.c: <-- download it as part of my eRCaGuy_hello_world repo

#include <stdbool.h> // For `true` (`1`) and `false` (`0`) macros in C
#include <stdint.h> // For `uint8_t`, `int8_t`, etc.
#include <stdio.h> // For `printf()`

typedef struct message_unpacked_s
{
uint16_t time;
uint16_t lat;
uint8_t ns;
uint16_t lon;
uint8_t ew;
} message_unpacked_t;

typedef struct __attribute__ ((__packed__)) message_s
{
uint16_t time;
uint16_t lat;
uint8_t ns;
uint16_t lon;
uint8_t ew;
} message_t;

typedef union message_converter_u
{
message_t message;
uint8_t bytes[sizeof(message_t)];
} message_converter_t;

// int main(int argc, char *argv[]) // alternative prototype
int main()
{
printf("This is the start of `main()`.\n");

// demonstrate that packing the struct matters
printf("sizeof(message_unpacked_t) = %zu bytes\n", sizeof(message_unpacked_t)); // 10 bytes due to padding
printf("sizeof(message_t) = %zu bytes\n", sizeof(message_t)); // 8 bytes

message_t message =
{
.time = 0x1234,
.lat = 0x2122,
.ns = 'n', // 0x6E
.lon = 0x1834,
.ew = 'e', // 0x65
};

message_converter_t converter;
// Note: copying `message` into `converter.message` here is unnecessarily inefficient. A
// more-efficient way is to simply construct the union type alone and populate the struct
// data inside the union directly. See "struct_to_array_via_type_punning_union_more_efficient.c"
// for that demo.
converter.message = message;

// Print the bytes
printf("bytes = [");
for (size_t i = 0; i < sizeof(converter.bytes); i++)
{
printf("0x%02X", converter.bytes[i]);
if (i < sizeof(converter.bytes) - 1)
{
printf(", ");
}
}
printf("]\n");

return 0;
}

Build and run command:

mkdir -p bin && gcc -Wall -Wextra -Werror -O3 -std=c11 -save-temps=obj struct_to_array_via_type_punning_union.c \
-o bin/struct_to_array_via_type_punning_union && bin/struct_to_array_via_type_punning_union

Sample output:

eRCaGuy_hello_world/c$ mkdir -p bin && gcc -Wall -Wextra -Werror -O3 -std=c11 -save-temps=obj struct_to_array_via_type_punning_union.c \
> -o bin/struct_to_array_via_type_punning_union && bin/struct_to_array_via_type_punning_union
This is the start of `main()`.
sizeof(message_unpacked_t) = 10 bytes
sizeof(message_t) = 8 bytes
bytes = [0x34, 0x12, 0x22, 0x21, 0x6E, 0x34, 0x18, 0x65]

More-efficient technique: do NOT copy from a struct to a union! Just use the union alone as your message_t!

struct_to_array_via_type_punning_union_more_efficient.c

#include <stdbool.h> // For `true` (`1`) and `false` (`0`) macros in C
#include <stdint.h> // For `uint8_t`, `int8_t`, etc.
#include <stdio.h> // For `printf()`

typedef struct message_data_unpacked_s
{
uint16_t time;
uint16_t lat;
uint8_t ns;
uint16_t lon;
uint8_t ew;
} message_data_unpacked_t;

typedef struct __attribute__ ((__packed__)) message_data_s
{
uint16_t time;
uint16_t lat;
uint8_t ns;
uint16_t lon;
uint8_t ew;
} message_data_t;

typedef union message_u
{
message_data_t data;
uint8_t bytes[sizeof(message_data_t)];
} message_t;

// int main(int argc, char *argv[]) // alternative prototype
int main()
{
printf("This is the start of `main()`.\n");

// demonstrate that packing the struct matters
printf("sizeof(message_data_unpacked_t) = %zu bytes\n", sizeof(message_data_unpacked_t)); // 10 bytes due to padding
printf("sizeof(message_data_t) = %zu bytes\n", sizeof(message_data_t)); // 8 bytes

message_t message =
{
.data =
{
.time = 0x1234,
.lat = 0x2122,
.ns = 'n', // 0x6E
.lon = 0x1834,
.ew = 'e', // 0x65
},
};

// Print the bytes
printf("bytes = [");
for (size_t i = 0; i < sizeof(message.bytes); i++)
{
printf("0x%02X", message.bytes[i]);
if (i < sizeof(message.bytes) - 1)
{
printf(", ");
}
}
printf("]\n");

return 0;
}

Sample output is the same as before:

eRCaGuy_hello_world/c$ mkdir -p bin && gcc -Wall -Wextra -Werror -O3 -std=c11 -save-temps=obj struct_to_array_via_type_punning_union_more_efficient.c \
> -o bin/struct_to_array_via_type_punning_union_more_efficient && bin/struct_to_array_via_type_punning_union_more_efficient
This is the start of `main()`.
sizeof(message_data_unpacked_t) = 10 bytes
sizeof(message_data_t) = 8 bytes
bytes = [0x34, 0x12, 0x22, 0x21, 0x6E, 0x34, 0x18, 0x65]

Keywords: c type punning; c struct to byte array conversion; c array to bytes; c serialization; c struct serialization; c object serialization

how to cast uint8_t array of 4 to uint32_t in c

Given the need to get uint8_t values to uint32_t, and the specs on in4_pton()...

Try this with a possible correction on the byte order:

uint32_t i32 = v4[0] | (v4[1] << 8) | (v4[2] << 16) | (v4[3] << 24);

Split UInt32 into [UInt8] in swift

Your loop can more compactly be written as

let byteArray = 24.stride(through: 0, by: -8).map {
UInt8(truncatingBitPattern: example >> UInt32($0))
}

Alternatively, create an UnsafeBufferPointer and convert that
to an array:

let example: UInt32 = 72 << 24 | 66 << 16 | 1 << 8 | 15

var bigEndian = example.bigEndian
let bytePtr = withUnsafePointer(&bigEndian) {
UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: sizeofValue(bigEndian))
}
let byteArray = Array(bytePtr)

print(byteArray) // [72, 66, 1, 15]

Update for Swift 3 (Xcode 8 beta 6):

var bigEndian = example.bigEndian
let count = MemoryLayout<UInt32>.size
let bytePtr = withUnsafePointer(to: &bigEndian) {
$0.withMemoryRebound(to: UInt8.self, capacity: count) {
UnsafeBufferPointer(start: $0, count: count)
}
}
let byteArray = Array(bytePtr)

How to split an Int to its individual digits?

We can also extend the StringProtocol and create a computed property:

edit/update: Xcode 11.5 • Swift 5.2

extension StringProtocol  {
var digits: [Int] { compactMap(\.wholeNumberValue) }
}


let string = "123456"
let digits = string.digits // [1, 2, 3, 4, 5, 6]


extension LosslessStringConvertible {
var string: String { .init(self) }
}

extension Numeric where Self: LosslessStringConvertible {
var digits: [Int] { string.digits }
}


let integer = 123
let integerDigits = integer.digits // [1, 2, 3]

let double = 12.34
let doubleDigits = double.digits // // [1, 2, 3, 4]

In Swift 5 now we can use the new Character property wholeNumberValue

let string = "123456"

let digits = string.compactMap{ $0.wholeNumberValue } // [1, 2, 3, 4, 5, 6]

Convert Bytes to Int / uint in C

Yes there is. Assume your bytes are in:

uint8_t bytes[N] = { /* whatever */ };

We know that, a 16 bit integer is just two 8 bit integers concatenated, i.e. one has a multiple of 256 or alternatively is shifted by 8:

uint16_t sixteen[N/2];

for (i = 0; i < N; i += 2)
sixteen[i/2] = bytes[i] | (uint16_t)bytes[i+1] << 8;
// assuming you have read your bytes little-endian

Similarly for 32 bits:

uint32_t thirty_two[N/4];

for (i = 0; i < N; i += 4)
thirty_two[i/4] = bytes[i] | (uint32_t)bytes[i+1] << 8
| (uint32_t)bytes[i+2] << 16 | (uint32_t)bytes[i+3] << 24;
// same assumption

If the bytes are read big-endian, of course you reverse the order:

bytes[i+1] | (uint16_t)bytes[i] << 8

and

bytes[i+3] | (uint32_t)bytes[i+2] << 8
| (uint32_t)bytes[i+1] << 16 | (uint32_t)bytes[i] << 24

Note that there's a difference between the endian-ness in the stored integer and the endian-ness of the running architecture. The endian-ness referred to in this answer is of the stored integer, i.e., the contents of bytes. The solutions are independent of the endian-ness of the running architecture since endian-ness is taken care of when shifting.

How do I convert an array of UInt64 to an array of UInt16 to perform multi-precision multiplication?

As mentioned by @JohnBollinger I was able to simply reinterpret the bytes of the array of uint64_t as an array of uint16_t by casting. For some reason, I was thinking the bytes had to be reordered somehow, but after testing I am getting the correct results. This didn't work for me initially because of other unrelated issues.



Related Topics



Leave a reply



Submit