I'm working with Particle Photon microcontroller and need to send a value >> 255 via TCP. I would need to convert this into an array of uint8_t so that I can use the client.write((int8_t *data), int sizeof(packet));
how can I achieve it?
Asked
Active
Viewed 844 times
-1

too honest for this site
- 12,050
- 4
- 30
- 52

Marco Datola
- 55
- 8
-
You can just assign it to the next `int8_t` in your array then shift right until you reach zero. This is is the easiest solution, but it puts the least significant bits first. – CompuChip Mar 22 '16 at 11:29
2 Answers
0
If possible, pick a consistent "endianness" for your data - "big endian" is typical for binary network protocols - it's used for the header fields in IP, UDP, TCP, etc.
Given that, you can then use the htonX
family of functions to convert the data from host format (whichever endian format that might be) to network format and then ntohX
on receipt to convert it back again, e.g.:
uint32_t netword = htonl(data);
[ On big-endian systems these functions become a "no-op" ]
EDIT oh - I missed the 'microcontroller' bit - chances are you don't have those functions available :(

Alnitak
- 334,560
- 70
- 407
- 495
-
Do you have any proof to suggest that on big systems those functions become no-op? Because I can't see any. – autistic Mar 22 '16 at 11:37
-
@Seb I don't know if a good compiler could completely optimise them away, but on a big-endian system `ntohX(v) == v`, i.e. it's the identity function. – Alnitak Mar 22 '16 at 11:39
-
This answer is wrong because you've confused "host byte order" with "host (whichever endian format that might be)". You think the 'h' part of htonl varies. It doesn't. Host byte order is **always** little endian. – autistic Mar 22 '16 at 11:42
-
So when you write `htonl(x)` you're saying `x` is in host byte order, and you want it converted to network byte order. It doesn't matter if it was already in network byte order, because you're telling it it's host byte order and you want it swapped. – autistic Mar 22 '16 at 11:43
-
@Seb you're absolutely wrong there - on *most* modern systems host order is little endian, but it's far from guaranteed. FWIW, network protocols are my speciality - when handling IETF binary protocols you should _always_ use `htonX` when writing to the wire and `ntohX` when reading from the wire. – Alnitak Mar 22 '16 at 11:45
-
OK, so maybe "always" was a little strong, you can do it with bit-twiddling too, but if `ntohX` exists then in theory it's more efficient than bit-twiddling (especially when host order == network order), and it _is_ the most portable, standards compliant method for the job, just like you demand in your profile. Your assertion that "host byte order is *always* little endian" is flat out wrong, regardless. – Alnitak Mar 22 '16 at 11:53
-
@AndrewHenle thanks, although I intentionally made it "community wiki" when I realised that it probably didn't apply in the OP's specific case so his downvote doesn't count for anything anyway :) – Alnitak Mar 22 '16 at 12:01
-
@Seb using `clang -O3` on OSX, `htonl` gets converted to a single `bswapl` instruction when the input is unknown, and when the input is a constant it gets optimised away completely, with the compiler replacing the constant with the byte-swapped equivalent. Bit-twiddling can't do that. – Alnitak Mar 22 '16 at 12:03
-
I thought I said I was departing from this conversation, hmmm... Are you talking about practical or theoretical? Because on one hand you say "in theory" and then on the other, you mention optimisations that are currently performed... Then you swap again by postulating on optimisations that you think can't exist. "An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced". Where's that proof I asked for so long ago? You haven't provided any citations... So far it's all anecdotal evidence. – autistic Mar 22 '16 at 13:19
-
@Seb I currently have no big-endian system on which I can "prove" that `htonX()` is a no-op, although mathematically it is undoubtably so, since on such a system it's equivalent to e.g. `uint32_t htonl(uint32_t n) { return n; }`. I had thought it extremely unlikely that a compiler could replace the typical set of eight shifts and masks with a single `bswap` instruction - it turns out I was wrong. Current versions of gcc and clang can both make that optimisation. – Alnitak Mar 22 '16 at 14:01
-
It looks like that optimisation depends on how you code it - if you marshall the four bytes through a `char` array per Lanting's deleted answer then gcc 5.3.1 can't spot the optimisation, although clang 7.3 can. – Alnitak Mar 22 '16 at 14:08
-
clang is also able to tell that `htonl(ntohl(x)) == x` and optimises away both calls. – Alnitak Mar 22 '16 at 14:11
-
Oh, and the OSX man page for `ntoh` etc says this: _"On machines which have a byte order which is the same as the network order, routines are defined as null macros."_ - I think that counts as some sort of proof. – Alnitak Mar 22 '16 at 14:20
-
Which OS X is that? Not all of them are considered strictly POSIX compliant, and OS X doesn't define POSIX; The Open Group does. – autistic Mar 23 '16 at 10:51
-
It's OS X 10.11 (El Capitan). The man page refers to POSIX-1.200x. That document in turn specifies that `ntohX` may be a macro (albeit without being specific that it'll be a null macro when host order = network order) – Alnitak Mar 23 '16 at 10:56
-2
used what ScruffR said on this post
EDIT previous version wasn't actually doing the job properly. adopted solution, that no one (despite down voting) provided
char buf[SIZEBUFF];
sprintf(buf,"%s",float2send);
sprintf(buf,"%ld",longInt2send);

Marco Datola
- 55
- 8