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

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

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位整数:

class Proxy {
private:
    uint16_t &_high, &_low;

public:
    Proxy(uint16_t &high, uint16_t &low) : _high(high), _low(low) {}

    Proxy &operator=(uint32_t whole) {
        _high = whole >> 16;
        _low = whole & 0xffff;
        return *this;
    }

    operator uint32_t() const {
        return (_high << 16) | _low;
    }
};

int main() {
    uint16_t high = 0xa, low = 0xb;
    Proxy whole(high, low);
    std::cout << std::hex;
    std::cout << whole << '\n'; // a000b
    high = 0xc;
    low = 0xd;
    std::cout << whole << '\n'; // c000d
    whole = 0xe000f;
    std::cout << high << ' ' << low << '\n'; // e f
    return 0;
}

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

英文:

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

class Proxy {
private:
    uint16_t &amp;_high, &amp;_low;

public:
    Proxy(uint16_t &amp;high, uint16_t &amp;low) : _high(high), _low(low) {}

    Proxy &amp;operator=(uint32_t whole) {
        _high = whole &gt;&gt; 16;
        _low = whole &amp; 0xffff;
        return *this;
    }

    operator uint32_t() const {
        return (_high &lt;&lt; 16) | _low;
    }
};

int main() {
    uint16_t high = 0xa, low = 0xb;
    Proxy whole(high, low);
    std::cout &lt;&lt; std::hex;
    std::cout &lt;&lt; whole &lt;&lt; &#39;\n&#39;; // a000b
    high = 0xc;
    low = 0xd;
    std::cout &lt;&lt; whole &lt;&lt; &#39;\n&#39;; // c000d
    whole = 0xe000f;
    std::cout &lt;&lt; high &lt;&lt; &#39; &#39; &lt;&lt; low &lt;&lt; &#39;\n&#39;; // e f
    return 0;
}

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

答案2

得分: 1

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

#include <iostream>
#include <array>
#include <cstdint>
#include <bit>
using std::uint32_t, std::uint16_t;

// 独立的函数
void place_low16(std::array<uint16_t, 2>& arr, uint16_t x) { arr[0] = x; }
void place_high16(std::array<uint16_t, 2>& arr, uint16_t x) { arr[1] = x; }
void place_32int(std::array<uint16_t, 2>& arr, uint32_t i) { arr = std::bit_cast<std::array<uint16_t, 2>>(i); }
uint32_t get_ui32(const std::array<uint16_t, 2>& arr) { return std::bit_cast<uint32_t>(arr); }

// 封装
struct PackedInt16 {
    std::array<uint16_t, 2> two_uint32s;
    void place_low16(uint16_t x) { two_uint32s[0] = x; }
    void place_high16(uint16_t x) { two_uint32s[1] = x; }
    void place_32int(uint32_t i) { two_uint32s = std::bit_cast<std::array<uint16_t, 2>>(i); }
    uint32_t get_ui32() { return std::bit_cast<uint32_t>(two_uint32s); }
};

int main() {
    // 独立的函数
    std::array<uint16_t, 2> packed_ints;
    place_low16(packed_ints, static_cast<uint16_t>(0xffff'ffff));   // 存储在低16位
    place_high16(packed_ints, static_cast<uint16_t>(0x1));          // 存储在高16位
    uint32_t x = get_ui32(packed_ints);                             // 获取32位整数
    place_32int(packed_ints, x);                                    // 将32位整数存储在打包的int16中
    std::cout << x << " " << packed_ints[0] << " " << packed_ints[1] << '\n';
    // 输出: 131071 65535 1

    // 封装
    PackedInt16 packed_ints2;
    packed_ints2.place_low16(static_cast<uint16_t>(0xffff'ffff));
    packed_ints2.place_high16(static_cast<uint16_t>(0x1));
    uint32_t x2 = packed_ints2.get_ui32();
    packed_ints2.place_32int(x2);
    std::cout << x2 << " " << packed_ints2.two_uint32s[0] << " " << packed_ints2.two_uint32s[1] << '\n';
    // 输出: 131071 65535 1

    // 直接方法:无函数,无类
    std::array<uint16_t, 2> packed_ints3;
    packed_ints3[0] = static_cast<uint16_t>(0xffff'ffff);
    packed_ints3[1] = 1;
    uint32_t x3 = std::bit_cast<uint32_t>(packed_ints3);
    packed_ints3 = std::bit_cast<std::array<uint16_t, 2>>(x3);
    std::cout << x3 << " " << packed_ints3[0] << " " << packed_ints3[1] << '\n';
    // 输出: 131071 65535 1
}
英文:

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:

#include &lt;iostream&gt;
#include &lt;array&gt;
#include &lt;cstdint&gt;
#include &lt;bit&gt;
using std::uint32_t, std::uint16_t;
// Free standing functions
void place_low16(std::array&lt;uint16_t, 2&gt;&amp; arr, uint16_t x) {arr[0] = x;}
void place_high16(std::array&lt;uint16_t, 2&gt;&amp; arr, uint16_t x) {arr[1] = x;}
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);}
uint32_t get_ui32(const std::array&lt;uint16_t, 2&gt;&amp; arr) {return std::bit_cast&lt;uint32_t&gt;(arr);}
// encapsulated
struct PackedInt16 {
std::array&lt;uint16_t, 2&gt; two_uint32s;
void place_low16(uint16_t x) {two_uint32s[0] = x;}
void place_high16(uint16_t x) { two_uint32s[1] = x; }
void place_32int(uint32_t i) { two_uint32s = std::bit_cast&lt;std::array&lt;uint16_t, 2&gt;&gt;(i); }
uint32_t get_ui32() { return std::bit_cast&lt;uint32_t&gt;(two_uint32s); }
};
int main()
{
// free standing functions
std::array&lt;uint16_t, 2&gt; packed_ints;
place_low16(packed_ints, static_cast&lt;uint16_t&gt;(0xffff&#39;ffff));   //store in low int16
place_high16(packed_ints, static_cast&lt;uint16_t&gt;(0x1));          // store in high int16
uint32_t x = get_ui32(packed_ints);                             // get 32 bit uint
place_32int(packed_ints, x);                                    // store 32 bit uint in packed int16s
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;;
// ouput: 131071 65535 1
// encapsulated
PackedInt16 packed_ints2;
packed_ints2.place_low16(static_cast&lt;uint16_t&gt;(0xffff&#39;ffff));
packed_ints2.place_high16(static_cast&lt;uint16_t&gt;(0x1));
uint32_t x2 = packed_ints2.get_ui32();
packed_ints2.place_32int(x2);
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;;
// ouput: 131071 65535 1
// and now the direct approach: No functions, no classes
std::array&lt;uint16_t, 2&gt; packed_ints3;
packed_ints3[0] = static_cast&lt;uint16_t&gt;(0xffff&#39;ffff);
packed_ints3[1] = 1;
uint32_t x3 = std::bit_cast&lt;uint32_t&gt;(packed_ints3);
packed_ints3 = std::bit_cast&lt;std::array&lt;uint16_t, 2&gt;&gt;(x3);
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;;
// ouput: 131071 65535 1
}

答案3

得分: 0

以下是翻译好的内容:

class Uint32BitView16
{
    uint32_t& m_data;
    unsigned m_shift;
public:
    constexpr Uint32BitView16(uint32_t& data, unsigned shift)
        : m_data(data),
        m_shift(shift)
    {
    }

    constexpr operator uint16_t() const
    {
        return (m_data >> m_shift);
    }

    constexpr Uint32BitView16& operator=(uint16_t value)
    {
        m_data = (m_data & ~static_cast<uint32_t>(0xffff << m_shift)) | (value << m_shift);
        return *this;
    }
};

int main() {
    uint32_t data = 0x01020304;
    Uint32BitView16 v1(data, 0);
    Uint32BitView16 v2(data, 16);

    std::cout << std::hex;

    std::cout << static_cast<uint16_t>(v1) << '\n'; // 304
    std::cout << static_cast<uint16_t>(v2) << '\n'; // 102

    data = 0xffff0000;
    std::cout << static_cast<uint16_t>(v1) << '\n'; // 0
    std::cout << static_cast<uint16_t>(v2) << '\n'; // ffff

    v1 = 0xff;
    std::cout << data << '\n'; // ffff00ff
}

希望这对你有帮助。

英文:

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.


class Uint32BitView16
{
uint32_t&amp; m_data;
unsigned m_shift;
public:
constexpr Uint32BitView16(uint32_t&amp; data, unsigned shift)
: m_data(data),
m_shift(shift)
{
}
constexpr operator uint16_t() const
{
return (m_data &gt;&gt; m_shift);
}
constexpr Uint32BitView16&amp; operator=(uint16_t value)
{
m_data = (m_data &amp; ~static_cast&lt;uint32_t&gt;(0xffff &lt;&lt; m_shift)) | (value &lt;&lt; m_shift);
return *this;
}
};
int main() {
uint32_t data = 0x01020304;
Uint32BitView16 v1(data, 0);
Uint32BitView16 v2(data, 16);
std::cout &lt;&lt; std::hex;
std::cout &lt;&lt; static_cast&lt;uint16_t&gt;(v1) &lt;&lt; &#39;\n&#39;; // 304
std::cout &lt;&lt; static_cast&lt;uint16_t&gt;(v2) &lt;&lt; &#39;\n&#39;; // 102
data = 0xffff0000;
std::cout &lt;&lt; static_cast&lt;uint16_t&gt;(v1) &lt;&lt; &#39;\n&#39;; // 0
std::cout &lt;&lt; static_cast&lt;uint16_t&gt;(v2) &lt;&lt; &#39;\n&#39;; // ffff
v1 = 0xff;
std::cout &lt;&lt; data &lt;&lt; &#39;\n&#39;; // ffff00ff
}

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:

确定