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
iOS - Could Not Open Obj File When Convert Mdlasset to Mdlmesh
How to Get an Array of Days Between Two Dates in Swift
Swift Framework with Opencv Dynamic Framework, Library Not Loaded
Prefix(_ Maxlength:) Is Type-Erased When Used with a Struct That Conforms to Lazysequenceprotocol
Redirect Process Stdout to Apple System Log Facility in Swift
How to Import Zbar Framework in Swift Project
Swift's Decimal Precision Issue
Difference Between Orientation and Rotation in Scnnode
Changing Associated Value of Enum Swift
Arkit: How to Tell If User's Face Is Parallel to Camera
Prepareforsegue from a UIbutton in a Custom Prototype Cell
How to Programmatically Scroll iOS Wkwebview, Swift 4
Allow Siri Remote Menu Button When Play/Pause Button Is Overridden
Collision Detection Leading to Color Detection
Is There Any Shorthand Way to Write Cgpoint, Cgrect, etc
Can't Unwrap Optional.None When Setting Window Background Color