![](/img/trans.png)
[英]Integer literal that matches int64_t for both 32-bit and 64-bit platforms?
[英]How to store and use two 32-bit signed int in one 64-bit int?
首先,我想澄清一下,这个问题与问题不同:
这个问题是 store and use ,这意味着我可以做到这一点
int64_t score = make_score(-15, 15);
score += make_score(-5, 5); //I can use (add, subtract) the score
int32_t a = get_a(score);
assert(a == -20); //-15 -5 = -20
int32_t b = get_b(score);
assert(b == 20);//15 + 5= 20
这对于一个 32 位 int 中的两个 16 位 int 是可以实现的( Stockfish 做到了这一点):
/// Score enum stores a middlegame and an endgame value in a single integer (enum).
/// The least significant 16 bits are used to store the middlegame value and the
/// upper 16 bits are used to store the endgame value. We have to take care to
/// avoid left-shifting a signed int to avoid undefined behavior.
enum Score : int { SCORE_ZERO };
constexpr Score make_score(int mg, int eg) {
return Score((int)((unsigned int)eg << 16) + mg);
}
/// Extracting the signed lower and upper 16 bits is not so trivial because
/// according to the standard a simple cast to short is implementation defined
/// and so is a right shift of a signed integer.
inline Value eg_value(Score s) {
union { uint16_t u; int16_t s; } eg = { uint16_t(unsigned(s + 0x8000) >> 16) };
return Value(eg.s);
}
inline Value mg_value(Score s) {
union { uint16_t u; int16_t s; } mg = { uint16_t(unsigned(s)) };
return Value(mg.s);
}
我正在尝试将mg
和eg
从int16_t
升级到int32_t
但我不知道该怎么做,当 ScoreA + ScoreB 破坏分数内的eg
和mg
时,我总是遇到麻烦。
这是我尝试但失败的方法:
enum Score : int64_t { SCORE_ZERO };
constexpr Score make_score(int mg, int eg) {
return Score((int)((uint64_t)eg << 32) + mg);
}
inline Value eg_value(Score s) {
union { uint32_t u; int32_t s; } eg = { uint32_t(unsigned(s + 0x80000000) >> 32) };
return Value(eg.s);
}
inline Value mg_value(Score s) {
union { uint32_t u; int32_t s; } mg = { uint32_t(unsigned(s)) };
return Value(mg.s);
}
使用memcpy
。
正如原始解决方案中的评论指出的那样,这种位操作是潜在未定义行为的雷区。 memcpy
允许您摆脱这些,并且现代编译器很好理解,因此它仍然会产生高效的机器代码。
enum Score : int64_t { SCORE_ZERO };
enum Value : int32_t { FORTYTWO };
inline Score make_score(int32_t mg, int32_t eg) {
int64_t combined;
std::memcpy(&combined, &eg, 4);
std::memcpy(reinterpret_cast<char*>(&combined) + 4, &mg, 4);
return Score(combined);
}
inline Value eg_value(Score s) {
int32_t eg;
std::memcpy(&eg, &s, 4);
return Value(eg);
}
inline Value mg_value(Score s) {
int32_t mg;
std::memcpy(&mg, reinterpret_cast<char*>(&s) + 4, 4);
return Value(mg);
}
问题是您仍然有一些“int”和“unsigned”关键字仍然可以转换为 32 位版本。 因此,将每个“int”替换为“int64_t”,将每个“unsigned”替换为“uint64_t”,它应该可以按预期工作。
对于这个问题,这可能是不同的方法
#include<iostream>
#include<cstdint>
#include<bitset>
using namespace std;
int main()
{
bitset<32> bit32[2] ={ 45 ,-415152545 };
bitset<64> bit64;
// store in 64 bit varibale
int index=0;
int position=0;
for(int i=0;i<64;i++)
{
bit64[i] =bit32[index][i-position];
if(i==31)
{ index = 1; position=32; }
}
// reset 32 bit container ,index and position
bit32[2] ={0};
index=0;
position=0;
// fetching data in 32 bit container from 64 bit and assign it into a and b .
int32_t a;
int32_t b;
for(int i=0;i<64;i++)
{
bit32[index][i-position] = bit64[i];
if(i==31)
{ index = 1; position=32; }
}
a = bit32[0].to_ulong();
b = bit32[1].to_ulong();
cout<<a<<" "<<b;
}
您也可以使用联合:
#include <stdint.h>
#include <iostream>
union Score {
int64_t u64;
int32_t u32[2];
Score() : u64(0) {}
Score(int64_t v) : u64(v) {}
Score(int32_t a, int32_t b): u32{a, b} {}
Score & operator=(Score const & original) { if(&original != this) { u64 = original.u64; } return *this; }
int32_t get_a() {return u32[0];}
int32_t get_b() {return u32[1];}
int64_t get() {return u64;}
Score operator+(Score const & other) {
return Score(u32[0] + other.u32[0], u32[1] + other.u32[1]);
}
Score & operator+=(Score const & other) {
u32[0] += other.u32[0];
u32[1] += other.u32[1];
return *this;
}
};
int main() {
Score v(-15, 15);
std::cout << "The size is: " << sizeof(Score) << " Bytes" << std::endl;
std::cout << "A is: " << v.get_a() << std::endl;
std::cout << "B is: " << v.get_b() << std::endl;
std::cout << "adding -5, +5" << std::endl;
Score v1 = v + Score(-5, 5);
std::cout << "A is: " << v1.get_a() << std::endl;
std::cout << "B is: " << v1.get_b() << std::endl;
std::cout << "adding -10, +10" << std::endl;
v += Score(-10, 10);
std::cout << "A is: " << v.get_a() << std::endl;
std::cout << "B is: " << v.get_b() << std::endl;
return 0;
}
Output:
The size is: 8 Bytes
A is: -15
B is: 15
adding -5, +5
A is: -20
B is: 20
adding -10, +10
A is: -25
B is: 25
这很简单。
int64_t value;
int32_t* value1 = (int32_t*)&value;
int32_t* value2 = (int32_t*)&value + 1;
例子:
#include <cstdint>
int main() {
int64_t value;
int32_t* value1 = (int32_t*)&value;
int32_t* value2 = (int32_t*)&value + 1;
*value1 = 10; // Example
*value2 = 20;
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.