I am looking for an elegant alternative of the following code where wordXX
contains always 16 bits:
uint64_t wordHi = 0xaa; // I would like u_int16_t over u_int64_t here
uint64_t wordMi = 0xbb; // because it represents the real data better
uint64_t wordLo = 0xcc;
uint64_t largeword = (wordHi << 32) + (wordMi << 16) + (wordLo << 0);
To me this (very simplified) code looks a bit dirty, because reader gets confused about the real size of the wordXX
data.
I could store wordHi
to largeword
and then shift largeword
and add wordMi
and so on, but this would make the code worse and probably needs more CPU cycles.
Edit: changed u_int64_t
to uint64_t
in the example as suggested in the comments.
2 Answers 2
Using uint16_t not a problem?
Your comment says you want to use uint16_t
, so why don't you do that? It would make the code look like this:
uint16_t wordHi = 0xaa;
uint16_t wordMi = 0xbb;
uint16_t wordLo = 0xcc;
uint64_t largeword = ((uint64_t) wordHi << 32) + ((uint64_t) wordMi << 16) + wordLo;
Use a struct and a union to do what you want. Note that this implementation is verbose and can be combined into a single declaration. Also depending on your system architecture, you may need to pack the struct or declare the members in a different order.
typedef struct
{
uint16_t Low;
uint16_t Mid;
uint16_t Hi;
uint16_t Spare;
} Word64_t;
typedef union
{
uint64_t Int64Val;
Word64_t WordVal;
} Splitter_t;
Splitter_t splitter;
splitter.WordVal.Low = 0xaa;
splitter.WordVal.Mid = 0xbb;
splitter.WordVal.Hi = 0xcc;
printf("%x", splitter.Int64Val); //should print 0xaabbcc
-
\$\begingroup\$ I think you would run into endianness issues with this solution. \$\endgroup\$JS1– JS12016年03月03日 01:39:48 +00:00Commented Mar 3, 2016 at 1:39
-
\$\begingroup\$ @JS1 That may be. It depends on the architecture, as I said. I do this all the time in embdeded. \$\endgroup\$Zack– Zack2016年03月03日 03:15:54 +00:00Commented Mar 3, 2016 at 3:15
-
\$\begingroup\$ If you can check the endianness of your architecture in a #define, you could define the order of elements in the struct differently based on the value of the #define. \$\endgroup\$user1118321– user11183212016年03月03日 03:34:42 +00:00Commented Mar 3, 2016 at 3:34
largeword = 0xaabbcc;
would not help me a lot. \$\endgroup\$wordMi
to 32-bit andwordLo
to 16-bit. But that makes it not much better... \$\endgroup\$u_int64_t
instead of the standarduint64_t
? Why aren't you usingu_int16_t
for the words? \$\endgroup\$