0

を16進数として出力しようとしていますunsigned intが、単に。を使用しているわけではありません%08X。最初にMSBの16進数と各バイトのLSBを印刷する必要があります。私はそれを得ました:

unsigned int num = 1234567890;
char *p = (char*)#
for (int i = 0; i < 4; i++) {
    printf("%X%X", (*(p+i) & 0xF0) >> 4, *(p+i) & 0x0F);
}
// prints: D2029649

unsigned intただし、次を含む文字列からに戻るのに問題がありD2029649ます。

short dehex(char hexLetter) {
  if(hexLetter > 47 && hexLetter < 58) hexLetter -= 48;
  if(hexLetter > 64) hexLetter -= 55;
  return hexLetter;  
}

unsigned int o = 0;
char *in = "D2029649";
int len = strlen(in);
for(int i = 0; i < len; i++) {
    if(i % 2 == 0) {
        o |= ((unsigned char)dehex(in[i]) << 4) + dehex(in[i+1]);
        o <<= 8;
    }
}

言うまでもなく、これはまったく機能しません。2行のコード操作oは、元のエンコーディングが行うことを元に戻そうとした結果と、バイトをintに戻す方法について行った調査の結果です。

おそらく私の問題は、ヘクスを生成しているときに実際に何をしているのかを完全に誤解していることにあります。

ヘックスを元のunsignedintに戻すための正しい方向に進むためのヒントはありますか?

4

1 に答える 1

1

演習の目的は、メモリレイアウトに基づいて整数を文字列に変換してから、元に戻すことであるように見えます。

そうでなければ、バイト境界にいるかどうかを判断してから、ビットシフトの「体操」を行うことをいじくり回すことはありません。むしろ、値を4だけ左にシフトして、次のように次の桁を追加します。

#include <stdio.h>
#include <string.h>

short dehex (char hexLetter) {
    if ((hexLetter >= '0') && (hexLetter <= '9'))
        return hexLetter - '0';
    return hexLetter - 'A' + 10;
}

int main (void) {
    unsigned int o = 0;
    char *in = "D2029649";
    int len = strlen (in);
    for (int i = 0; i < len; i++)
            o  = (o << 4) + dehex (in[i]);
    printf ("%X\n", o);
    return 0;
}

dehex文字定数がはるかに読みやすいマジックナンバーの大ファンではないため、関数を少し変更したことに気付くでしょう(EBCDICなどのすべての実装に移植できるわけではありませんが、最近では貴重なものはほとんどありません。 )。

このプログラムは、チェックのために、その文字列から符号なし整数値を大文字の16進数で出力しますD2029649

ただし、123456789010進数の値は、16進数で499602D2、文字列にあるバイトの順序とは逆のバイトの順序になっています。これは、リトルエンディアンアーキテクチャとして知られているものを使用しているためです。

したがって、2つの問題があります。

1つ目は、元の番号を取得するために間違った順序でバイトを処理していることです。

文字列の最後から始めて、次のように逆方向に作業する必要があります。

for (int i = len - 2; i >= 0; i -= 2) ...

2つ目は、追加/シフト操作を間違った順序で実行していることです。

元のコードは追加D2029649にシフトしたため、左に8ビットシフトし02964900D2から、左から忘却にシフトし、右に0バイトがシフトインしました。シフトしてから追加する必要があります:

o <<= 8;
o |= ((unsigned char)dehex(in[i]) << 4) + dehex(in[i+1]);

最後に、必須ではありませんが、変換されたニブルを返すためにunsigned charを使用するだけで、コードをかなり単純化できます。私が書くコードは次の行に沿っています:

#include <stdio.h>
#include <string.h>

unsigned char dehex (char hexLetter) {
    if ((hexLetter >= '0') && (hexLetter <= '9'))
        return hexLetter - '0';
    return hexLetter - 'A' + 10;
}

int main (void) {
    unsigned int num = 1234567890;
    char *p = (char*) &num;
    for (int i = 0; i < 4; i++)
        printf("%X%X", (*(p+i) & 0xF0) >> 4, *(p+i) & 0x0F);
    putchar ('\n');

    unsigned int o = 0;
    char *in = "D2029649";
    int len = strlen (in);
    for (int i = len - 2; i >= 0; i -= 2) {
        o <<= 8;
        o |= (dehex (in[i]) << 4) + dehex (in[i+1]);
    }
    printf ("%X, or %u\n", o, o);
    return 0;
}

これは、一度にニブルではなく、一度に1バイトずつ実行するという点ではるかに理にかなっていることに注意してください。ニブルベースのコードでは、小さなループ6, 7, 4, 5, 2, 3, 0, 1ではなく、配列インデックスを順番に実行する必要があります。0..7

このプログラムの出力は次のとおりです。

D2029649
499602D2, or 1234567890

元の番号に戻っていることを示しています。

于 2012-10-04T01:24:44.063 に答える