在C++中将两个整数合并为一个更大的整数。

huangapple go评论109阅读模式
英文:

Joining two integers into one bigger integer in C++

问题

我需要有两个独立的16位整数,它们可以一起组成一个32位整数。但无论我更改它们中的任何一个,我都需要它们被更新。假设我更改了32位整数的值,我需要它自动覆盖两个16位整数,反之亦然。这是可能的吗?

英文:

I need to have two separate 16-bit integers, that can form a 32-bit integer together. But I need them to be updated whenever I change any of them. Let's say I change the value of the 32-bit, I need it to be automatically written over the two 16-bit ones and vice versa. Is this possible?

答案1

得分: 8

你可以使用代理类来表示你的32位整数:

  1. class Proxy {
  2. private:
  3. uint16_t &_high, &_low;
  4. public:
  5. Proxy(uint16_t &high, uint16_t &low) : _high(high), _low(low) {}
  6. Proxy &operator=(uint32_t whole) {
  7. _high = whole >> 16;
  8. _low = whole & 0xffff;
  9. return *this;
  10. }
  11. operator uint32_t() const {
  12. return (_high << 16) | _low;
  13. }
  14. };
  15. int main() {
  16. uint16_t high = 0xa, low = 0xb;
  17. Proxy whole(high, low);
  18. std::cout << std::hex;
  19. std::cout << whole << '\n'; // a000b
  20. high = 0xc;
  21. low = 0xd;
  22. std::cout << whole << '\n'; // c000d
  23. whole = 0xe000f;
  24. std::cout << high << ' ' << low << '\n'; // e f
  25. return 0;
  26. }

通过提供operator uint32_tProxy在大多数情况下可以隐式转换为uint32_t

英文:

You can use a proxy class to represent your 32-bit integer:

  1. class Proxy {
  2. private:
  3. uint16_t &amp;_high, &amp;_low;
  4. public:
  5. Proxy(uint16_t &amp;high, uint16_t &amp;low) : _high(high), _low(low) {}
  6. Proxy &amp;operator=(uint32_t whole) {
  7. _high = whole &gt;&gt; 16;
  8. _low = whole &amp; 0xffff;
  9. return *this;
  10. }
  11. operator uint32_t() const {
  12. return (_high &lt;&lt; 16) | _low;
  13. }
  14. };
  15. int main() {
  16. uint16_t high = 0xa, low = 0xb;
  17. Proxy whole(high, low);
  18. std::cout &lt;&lt; std::hex;
  19. std::cout &lt;&lt; whole &lt;&lt; &#39;\n&#39;; // a000b
  20. high = 0xc;
  21. low = 0xd;
  22. std::cout &lt;&lt; whole &lt;&lt; &#39;\n&#39;; // c000d
  23. whole = 0xe000f;
  24. std::cout &lt;&lt; high &lt;&lt; &#39; &#39; &lt;&lt; low &lt;&lt; &#39;\n&#39;; // e f
  25. return 0;
  26. }

By providing operator uint32_t, Proxy can be implicitly converted to uint32_t in most cases.

答案2

得分: 1

这在C++20中变得非常容易,它具有bit_cast功能,甚至可以在constexpr函数中使用。以下是三种不同方式的示例代码:

  1. #include <iostream>
  2. #include <array>
  3. #include <cstdint>
  4. #include <bit>
  5. using std::uint32_t, std::uint16_t;
  6. // 独立的函数
  7. void place_low16(std::array<uint16_t, 2>& arr, uint16_t x) { arr[0] = x; }
  8. void place_high16(std::array<uint16_t, 2>& arr, uint16_t x) { arr[1] = x; }
  9. void place_32int(std::array<uint16_t, 2>& arr, uint32_t i) { arr = std::bit_cast<std::array<uint16_t, 2>>(i); }
  10. uint32_t get_ui32(const std::array<uint16_t, 2>& arr) { return std::bit_cast<uint32_t>(arr); }
  11. // 封装
  12. struct PackedInt16 {
  13. std::array<uint16_t, 2> two_uint32s;
  14. void place_low16(uint16_t x) { two_uint32s[0] = x; }
  15. void place_high16(uint16_t x) { two_uint32s[1] = x; }
  16. void place_32int(uint32_t i) { two_uint32s = std::bit_cast<std::array<uint16_t, 2>>(i); }
  17. uint32_t get_ui32() { return std::bit_cast<uint32_t>(two_uint32s); }
  18. };
  19. int main() {
  20. // 独立的函数
  21. std::array<uint16_t, 2> packed_ints;
  22. place_low16(packed_ints, static_cast<uint16_t>(0xffff'ffff)); // 存储在低16位
  23. place_high16(packed_ints, static_cast<uint16_t>(0x1)); // 存储在高16位
  24. uint32_t x = get_ui32(packed_ints); // 获取32位整数
  25. place_32int(packed_ints, x); // 将32位整数存储在打包的int16中
  26. std::cout << x << " " << packed_ints[0] << " " << packed_ints[1] << '\n';
  27. // 输出: 131071 65535 1
  28. // 封装
  29. PackedInt16 packed_ints2;
  30. packed_ints2.place_low16(static_cast<uint16_t>(0xffff'ffff));
  31. packed_ints2.place_high16(static_cast<uint16_t>(0x1));
  32. uint32_t x2 = packed_ints2.get_ui32();
  33. packed_ints2.place_32int(x2);
  34. std::cout << x2 << " " << packed_ints2.two_uint32s[0] << " " << packed_ints2.two_uint32s[1] << '\n';
  35. // 输出: 131071 65535 1
  36. // 直接方法:无函数,无类
  37. std::array<uint16_t, 2> packed_ints3;
  38. packed_ints3[0] = static_cast<uint16_t>(0xffff'ffff);
  39. packed_ints3[1] = 1;
  40. uint32_t x3 = std::bit_cast<uint32_t>(packed_ints3);
  41. packed_ints3 = std::bit_cast<std::array<uint16_t, 2>>(x3);
  42. std::cout << x3 << " " << packed_ints3[0] << " " << packed_ints3[1] << '\n';
  43. // 输出: 131071 65535 1
  44. }
英文:

This gets really easy with c++20 which has bit_cast. It can even be used in constexpr functions. Here are freestanding encapsulated, and really simple direct (no extra functions or classes) versions:

  1. #include &lt;iostream&gt;
  2. #include &lt;array&gt;
  3. #include &lt;cstdint&gt;
  4. #include &lt;bit&gt;
  5. using std::uint32_t, std::uint16_t;
  6. // Free standing functions
  7. void place_low16(std::array&lt;uint16_t, 2&gt;&amp; arr, uint16_t x) {arr[0] = x;}
  8. void place_high16(std::array&lt;uint16_t, 2&gt;&amp; arr, uint16_t x) {arr[1] = x;}
  9. void place_32int(std::array&lt;uint16_t, 2&gt;&amp; arr, uint32_t i){arr = std::bit_cast&lt;std::array&lt;uint16_t, 2&gt;&gt;(i);}
  10. uint32_t get_ui32(const std::array&lt;uint16_t, 2&gt;&amp; arr) {return std::bit_cast&lt;uint32_t&gt;(arr);}
  11. // encapsulated
  12. struct PackedInt16 {
  13. std::array&lt;uint16_t, 2&gt; two_uint32s;
  14. void place_low16(uint16_t x) {two_uint32s[0] = x;}
  15. void place_high16(uint16_t x) { two_uint32s[1] = x; }
  16. void place_32int(uint32_t i) { two_uint32s = std::bit_cast&lt;std::array&lt;uint16_t, 2&gt;&gt;(i); }
  17. uint32_t get_ui32() { return std::bit_cast&lt;uint32_t&gt;(two_uint32s); }
  18. };
  19. int main()
  20. {
  21. // free standing functions
  22. std::array&lt;uint16_t, 2&gt; packed_ints;
  23. place_low16(packed_ints, static_cast&lt;uint16_t&gt;(0xffff&#39;ffff)); //store in low int16
  24. place_high16(packed_ints, static_cast&lt;uint16_t&gt;(0x1)); // store in high int16
  25. uint32_t x = get_ui32(packed_ints); // get 32 bit uint
  26. place_32int(packed_ints, x); // store 32 bit uint in packed int16s
  27. std::cout &lt;&lt; x &lt;&lt; &quot; &quot; &lt;&lt; packed_ints[0] &lt;&lt; &quot; &quot; &lt;&lt; packed_ints[1] &lt;&lt; &#39;\n&#39;;
  28. // ouput: 131071 65535 1
  29. // encapsulated
  30. PackedInt16 packed_ints2;
  31. packed_ints2.place_low16(static_cast&lt;uint16_t&gt;(0xffff&#39;ffff));
  32. packed_ints2.place_high16(static_cast&lt;uint16_t&gt;(0x1));
  33. uint32_t x2 = packed_ints2.get_ui32();
  34. packed_ints2.place_32int(x2);
  35. std::cout &lt;&lt; x2 &lt;&lt; &quot; &quot; &lt;&lt; packed_ints2.two_uint32s[0] &lt;&lt; &quot; &quot; &lt;&lt; packed_ints2.two_uint32s[1] &lt;&lt; &#39;\n&#39;;
  36. // ouput: 131071 65535 1
  37. // and now the direct approach: No functions, no classes
  38. std::array&lt;uint16_t, 2&gt; packed_ints3;
  39. packed_ints3[0] = static_cast&lt;uint16_t&gt;(0xffff&#39;ffff);
  40. packed_ints3[1] = 1;
  41. uint32_t x3 = std::bit_cast&lt;uint32_t&gt;(packed_ints3);
  42. packed_ints3 = std::bit_cast&lt;std::array&lt;uint16_t, 2&gt;&gt;(x3);
  43. std::cout &lt;&lt; x3 &lt;&lt; &quot; &quot; &lt;&lt; packed_ints3[0] &lt;&lt; &quot; &quot; &lt;&lt; packed_ints3[1] &lt;&lt; &#39;\n&#39;;
  44. // ouput: 131071 65535 1
  45. }

答案3

得分: 0

以下是翻译好的内容:

  1. class Uint32BitView16
  2. {
  3. uint32_t& m_data;
  4. unsigned m_shift;
  5. public:
  6. constexpr Uint32BitView16(uint32_t& data, unsigned shift)
  7. : m_data(data),
  8. m_shift(shift)
  9. {
  10. }
  11. constexpr operator uint16_t() const
  12. {
  13. return (m_data >> m_shift);
  14. }
  15. constexpr Uint32BitView16& operator=(uint16_t value)
  16. {
  17. m_data = (m_data & ~static_cast<uint32_t>(0xffff << m_shift)) | (value << m_shift);
  18. return *this;
  19. }
  20. };
  21. int main() {
  22. uint32_t data = 0x01020304;
  23. Uint32BitView16 v1(data, 0);
  24. Uint32BitView16 v2(data, 16);
  25. std::cout << std::hex;
  26. std::cout << static_cast<uint16_t>(v1) << '\n'; // 304
  27. std::cout << static_cast<uint16_t>(v2) << '\n'; // 102
  28. data = 0xffff0000;
  29. std::cout << static_cast<uint16_t>(v1) << '\n'; // 0
  30. std::cout << static_cast<uint16_t>(v2) << '\n'; // ffff
  31. v1 = 0xff;
  32. std::cout << data << '\n'; // ffff00ff
  33. }

希望这对你有帮助。

英文:

You could define a class that behaves similar to a uint16_t which works with a uint32_t value stored as reference.

In some cases there's a difference though, e.g. a conversion to uint16_t won't happen automatically in some cases.

  1. class Uint32BitView16
  2. {
  3. uint32_t&amp; m_data;
  4. unsigned m_shift;
  5. public:
  6. constexpr Uint32BitView16(uint32_t&amp; data, unsigned shift)
  7. : m_data(data),
  8. m_shift(shift)
  9. {
  10. }
  11. constexpr operator uint16_t() const
  12. {
  13. return (m_data &gt;&gt; m_shift);
  14. }
  15. constexpr Uint32BitView16&amp; operator=(uint16_t value)
  16. {
  17. m_data = (m_data &amp; ~static_cast&lt;uint32_t&gt;(0xffff &lt;&lt; m_shift)) | (value &lt;&lt; m_shift);
  18. return *this;
  19. }
  20. };
  21. int main() {
  22. uint32_t data = 0x01020304;
  23. Uint32BitView16 v1(data, 0);
  24. Uint32BitView16 v2(data, 16);
  25. std::cout &lt;&lt; std::hex;
  26. std::cout &lt;&lt; static_cast&lt;uint16_t&gt;(v1) &lt;&lt; &#39;\n&#39;; // 304
  27. std::cout &lt;&lt; static_cast&lt;uint16_t&gt;(v2) &lt;&lt; &#39;\n&#39;; // 102
  28. data = 0xffff0000;
  29. std::cout &lt;&lt; static_cast&lt;uint16_t&gt;(v1) &lt;&lt; &#39;\n&#39;; // 0
  30. std::cout &lt;&lt; static_cast&lt;uint16_t&gt;(v2) &lt;&lt; &#39;\n&#39;; // ffff
  31. v1 = 0xff;
  32. std::cout &lt;&lt; data &lt;&lt; &#39;\n&#39;; // ffff00ff
  33. }

huangapple
  • 本文由 发表于 2023年2月9日 02:28:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75390227.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定