2

次のようなアドレスとオフセットがあるとします。

   char* base_addr = "\x00\x00\x00\xb7";
   char* addr_offset = (user input);

base_addr と addr_offset を一緒に追加したい。NUL で終了しない独自の strtol() 関数を作成する必要がありますか、または 2 つのアドレスを正常に追加できる別の方法がありますか?

編集:

これが Linux x86 であることを忘れていました。

4

1 に答える 1

1

base_addrは実際には 32 ビットの整数値であり、たまたまバイト定数を使用してハードコードされています。ポインターの型を にキャストし、ユーザーが入力した文字列unsigned longを呼び出しstrtol()て、2 つを合計するだけです。

そのように文字列を使用してポインターをハードコーディングするのは不十分です。1 つには、C は文字列の末尾に NUL バイトを追加するため、32 ビット値は 5 バイトになり、パディング バイトを追加すると、ポインターを格納するために 8 バイトを使用することになり、必要なバイト数のちょうど 2 倍になります。 . このようにする方が良い:

char base_addr[] = {'\x00', '\x00', '\x00', '\xb7'};

コンパイラが型キャストを許可する限り、あなたが何を意味するかを言う方がさらに良いです:

unsigned char *base_addr = (unsigned char *)0xb7000000;

確認したところ、GCC を使用すると、エラーや警告なしで上記を実行できます。

編集:ああ、わかりました、本当の問題は、整数値内のバイトにアクセスする方法です。

ポインタをいじるだけでこれを行うことができるはずです:

unsigned long base_adr = 0xb700000000;
unsigned char *p = (unsigned char *)&base_adr;

上記のトリックは整数型で機能します。それを行う別の方法は、C ユニオンを使用することです。

typedef union
{
    char bytes[4];
    unsigned long n;
    unsigned char *ptr;
} ADR_WINDOW;

ADR_WINDOW x;

x.n = 0xb700000000;
assert(x.bytes[3] == 0xb7); // on a little-endian computer
assert(x.bytes[0] == 0xb7); // on a big-endian computer

ユニオン トリックはどの型でも機能し、float 値内のビットを調べるような卑劣なトリックを行う唯一の移植可能な方法です。

于 2012-06-12T20:53:56.510 に答える