C++|将int转换为byte[4],反之亦然

bybem2ql  于 2023-06-07  发布在  其他
关注(0)|答案(5)|浏览(217)

我试图将整数转换为字节(又名无符号字符)数组,以便在C++中通过TCP流发送数组,反之亦然。
我已经尝试了许多解决方案的stackoverflow和自己的想法,但似乎没有真正为我工作。
我的最后一个解决方案看起来像这样:

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include "tcpconnector.h"

typedef unsigned char byte;

using namespace std;

/*
char* byteToChar(byte* b, int length) {
    char c[length];
    for (int i = 0; i < length; i++) {
    c[i] = b[i] - 128;
    }
    return c;
}

byte* charToByte(char* c, int length) {
    byte b[length];
    for (int i = 0; i < length; i++) {
    b[i] = c[i] + 128;
    }
    return b;
}
*/

byte* intToByte(int n) {

    byte byte[4];

     byte[0] = n & 0x000000ff;
     byte[1] = n & 0x0000ff00 >> 8;
     byte[2] = n & 0x00ff0000 >> 16;
     byte[3] = n & 0xff000000 >> 24; 

     return byte;
}

int byteToInt(byte* byte) {

    int n = 0;

    n = n + (byte[0] & 0x000000ff);
    n = n + ((byte[1] & 0x000000ff) << 8);
    n = n + ((byte[2] & 0x000000ff) << 16);
    n = n + ((byte[3] & 0x000000ff) << 24);

    return n;
}

int main(int argc, char** argv)
{
    if (argc != 3) {
        printf("usage: %s <port> <ip>\n", argv[0]);
        exit(1);
    }

    int number = 42;
    byte* line = intToByte(number);

    cout << "Number: " << number << "\n";
    cout << "ArrayLength: " << sizeof line << "\n";
    cout << "Array: " << line << "\n";
    cout << "Array to Number: " << byteToInt(line) << "\n";

/*

    TCPConnector* connector = new TCPConnector();
    TCPStream* stream = connector->connect(argv[2], atoi(argv[1]));
    if (stream) {
        stream->send(byteToChar(line, 4), 4);
        delete stream;
    }

*/
    exit(0);
}

每次我执行这段代码,我得到的结果是“4202308”,无论我设置为“int number”。
任何帮助将不胜感激。
更新:

void intToByte(int n, byte* result) {

     result[0] = n & 0x000000ff;
     result[1] = n & 0x0000ff00 >> 8;
     result[2] = n & 0x00ff0000 >> 16;
     result[3] = n & 0xff000000 >> 24; 
}

引用main():

int number = 42;
byte line[4];
intToByte(number, line);

cout << "Number: " << number << "\n";
cout << "ArrayLength: " << sizeof line << "\n";
cout << "Array: " << line << "\n";
cout << "Array to Number: " << byteToInt(line) << "\n";
ssm49v7z

ssm49v7z1#

你的intToByte函数在其函数体的作用域内分配了一个byte[4],然后返回一个指向它的指针。
因此,一旦你的函数返回,值就会被丢弃,调用者收到的只是一个指向现在无效的位置的指针--当值超出范围时,它们就会被销毁,指针不会延长其生命周期。
要么使用标准容器对象,如std::arraystd::vector,您的函数应返回给调用者,要么让intToByte接受byte[4]/byte*作为参数并将其填充。
为了完整性...你也可以让函数使用new创建字节数组,但是你必须记住delete[]它,虽然在这种情况下看起来很容易,但当你没有很好的理由进行动态分配时,这通常是不好的做法。
此外,x & y >> z语句将首先执行y >> z,然后 * 再 * 将结果与x进行位与运算,这当然不是您想要的结果。

anhgbhbe

anhgbhbe2#

**第一点:**从byte* intToByte(int n)返回的缓冲区不安全。返回的是本地数组的基址。要么传递一个字节数组作为输入,要么在堆中分配字节并返回地址
第二点:

考虑运算符优先级。

byte byte[4];
 byte[0] = n & 0x000000ff;
 byte[1] = ( n & 0x0000ff00 ) >> 8;
 byte[2] = ( n & 0x00ff0000 ) >> 16;
 byte[3] = ( n & 0xff000000 ) >> 24;
pkwftd7m

pkwftd7m3#

这个函数将所有标准的C++类型转换为字节向量。

template <typename T>
std::vector<byte> ToByte(T input) 
{
    byte* bytePointer = reinterpret_cast<byte*>(&input);
    return std::vector<byte>(bytePointer, bytePointer + sizeof(T));
}
zkure5ic

zkure5ic4#

不幸的是,这不是对您问题的确切答案,但可能会有所帮助。你可以像下面的代码一样做我想。

#include <stdio.h>
using namespace std;

unsigned char* intToByte(const int& N) {

    unsigned char* byte = new unsigned char[4];

    byte[0] = (N >> 24) & 0xFF;
    byte[1] = (N >> 16) & 0xFF;
    byte[2] = (N >> 8) & 0xFF;
    byte[3] = N & 0xFF;

    return byte;
}

int main()
{
    unsigned char * result = intToByte(255);
    printf("%x %x %x %x\n", (unsigned char)result[0], (unsigned char)result[1],
                            (unsigned char)result[2], (unsigned char)result[3]);

    delete result;
    return 0;
}
whlutmcx

whlutmcx5#

如果有人正在寻找现代C++20解决方案(在标准库中)。
这里有两个很好的模板化函数,可以将基本类型(如int,short等)转换为字节,并转换为必要的endianness:

template<typename T, std::endian to_endianness = std::endian::big>
std::vector<uint8_t> toBytes(T value)
{
    std::vector<uint8_t> buffer(sizeof(T));

    std::copy_n(reinterpret_cast<uint8_t*>(&value), sizeof(T), buffer.begin());

    if constexpr (std::endian::native != to_endianness)
        std::reverse(buffer.begin(), buffer.end());

    return buffer;
}

...要从字节转换,您可以用途:

template<typename T, std::endian from_endianness = std::endian::big>
T fromBytes(std::vector<uint8_t> bytes)
{
    if constexpr (std::endian::native != from_endianness)
        std::reverse(bytes.begin(), bytes.end());

    T* buffer = reinterpret_cast<T*>(bytes.data());

    return *buffer;
}

为了保持代码简单,我特意删除了混合字节序和std::is_fundamental<T>的检查,如果需要,您可以在我的GitHub gist(Unlicense license)上看到这些检查的代码。

相关问题