0

unsigned longソケット経由でいくつかの s を送信する必要があります。anunsigned longが 4 バイトであるため、受信側は 4 バイトのみを予期します。私が書いた変換関数は以下のように機能しますが、char に格納する必要がある数値が 127 resp よりも大きくない場合にのみ機能します。0x7F。0x7f より大きい値の場合、拡張 ASCII テーブル ( http://www.asciitable.com/ )に従って文字が文字に格納されると予想されますが、そうではありません。たとえば 0x90 の場合、何も保存されません。Unicode 文字セットで VS12 を使用しています。

変換を正しくする方法はありますか?

void number2char(unsigned long number, char* nrAsByte){
    std::stringstream numberSS;
    numberSS << std::hex << number;
    int length = numberSS.str().length();
    length = length / 2.0 + 0.5;
    nrAsByte = new char[sizeof(number)]();
    std::fill(nrAsByte, nrAsByte + length, '\x20');
    while (length > 0){
        int lastTwo = (number & 0xff);
        number >>= 8;
        unsigned char a = lastTwo;  // this doesn't work if lastTwo > 0x7F
        std::memcpy(nrAsByte + length - 1, &a, 1);
        --length;
    }
}

コードについて申し訳ありません。私が十分にテストしておらず、バグが含まれています。使用しないでください。代わりに回答のアドバイスに従ってください

4

2 に答える 2

2

次のようなものではないのはなぜですか:

void number2char(unsigned long number, char* nrAsByte){
   unsigned char *dst= reinterpret_cast<unsigned char *> nrAsByte;
   for (int i=0; i<sizeof(unsigned long); ++i) {
      *dst++= number & 0xFF;
      number >>= 8;
   }
}
于 2016-07-13T08:25:47.823 に答える
1

うーん、私はアントニオの答えをいじっていました。完全で正しいとは感じなかったので、最終的には予想よりも複雑なもので終わりましたが、複雑さには目的がある場合があります。

次のコードは、とりわけ手動でhtonl/のntohlような変換を行っています (おそらく反対のエンディアンであるため、これを と混ぜhtonlたり、どちらかを使用したり、 で書き直したりすることは望ましくありませんhtonl)。

Antonio のソースとは異なり、入力数値型が 8 バイト長の場合 (unsigned long私のテストプラットフォームでは 8 バイトです- 試してみてください?!)、メモリを上書きしません。代わりに、目的のネットワーク char* バッファーに収まるように値を切り捨てます。

さらに複雑さを追加するための各決定の背後にあるアイデアを提供するために、広範囲にコメントしようとしました(基本的にunsigned int numberused asを使用しているもの(char *)(&number)に、これも提供しますが、エンディアンを保護せず、異なる長さの型を混同するとメモリを上書きする可能性があります)。しかし、不明な点があれば何でも聞いてください。

#include <iostream>
#include <string>

// Experiment with different types to see differences
// (and how data are truncated when sizeof number > sizeof networkdata)

//typedef unsigned int numberType_t;
typedef unsigned long numberType_t;  // on my platform this is 8 bytes long

constexpr int networkBytesSize = 4;  // number of chars to be sent trough network with (char *)
// define network data type:
// used "struct" to make sizeof(networkData_t) return actual number of bytes
typedef struct {
    unsigned char d[networkBytesSize];
    char *cptr() { return reinterpret_cast<char *>(d); }
} networkData_t;

// Writes number into network char* buffer nrAsByte, endianness agnostic
void number2char(numberType_t number, networkData_t & nrAsByte) {
    for (size_t i = 0; i < sizeof(networkData_t); ++i) {
        nrAsByte.d[i] = number & 0xFF;
        number >>= 8;
    }
}

// Read number back from network char* buffer
numberType_t char2number(const networkData_t & nrAsByte) {
    numberType_t number = 0;
    size_t i = sizeof(networkData_t);
    while (i--) number = (number<<8) | nrAsByte.d[i];
    return number;
}

int main()
{
    printf("numberType_t size in bytes: %lu, networkData_t size in bytes: %lu\nAll following numbers are hex:\n",
            sizeof(numberType_t), sizeof(networkData_t));

    numberType_t number = numberType_t(0x9ABCDEF0123456FEul);
    std::cout << "source number: " << std::hex << number << std::endl;

    // Write number into char buffer
    networkData_t networkData;
    number2char(number, networkData);
    std::cout << "network bytes:";
    for (size_t i = 0; i < sizeof(networkData_t); ++i) std::cout << " [" << unsigned(networkData.d[i]) << "]";
    std::cout << std::endl;

    // Test usability of (char *) pointer access
    const char * testCharPtrConversion = networkData.cptr();
    printf("as char * (decimal signed): %d %d ...\n", testCharPtrConversion[0], testCharPtrConversion[1]);

    // Read number from char buffer
    number = char2number(networkData);
    std::cout << "read number: 0x" << std::hex << number << std::endl;
}
于 2016-07-13T12:11:16.130 に答える