0

64ビットLinux、カーネル2.6.xで次のコードがあります。私の理解では、最初の mallocrrr=malloc(8)はヒープに 8 バイトを割り当て、 rrr にはこれらの 8 バイトの開始アドレスの値が含まれています。それから、私は何かクレイジーなことをします。に示すように、8 バイトのポインターを 1 バイトに格納しようとしています*rrr = malloc(8)。次に、5番目のバイトで同じことを行います。1 バイトは 255 までの値しか保持できませんが、これらのバイトに格納されている値を出力すると、値が 255 よりも大きくなります。説明していただけますか?

#include <stdlib.h>
#include <stdio.h>

void ** rrr;
int main(int argc, char ** argv)
{
  rrr = malloc(8); // rrr should point to the starting address of an 8 byte block
  *rrr = malloc(8);
  *(rrr+5) = malloc(8);

  for(int i =0;i< 8;i++)
    printf("*rrr%d: %p\n", i, *(rrr+i)); // should print what is stored in each byte

 return 0;
}

上記の 1 回の実行が返されます

*rrr0: 0x9ae030
*rrr1: (nil)
*rrr2: (nil)
*rrr3: 0x21
*rrr4: (nil)
*rrr5: 0x9ae050
*rrr6: (nil)
*rrr7: 0x21
4

3 に答える 3

1

8 バイトのポインターを 1 バイトに格納しようとしています

コードに単一バイトはありません。 rrrはポインターであり、そうです*rrr(ポインターからポインターとして宣言rrrしたため)。

ただし、ここで未定義の動作を呼び出していることはほぼ確実です。が 1 でない限りsizeof(void *)(これは非常にありそうもないことです!)、 への書き込み*(rrr+5)は、割り当てたメモリの境界を超えて書き込むことになります。

于 2013-02-09T21:18:42.653 に答える
1

1 バイトは 255 までの値しか保持できませんが、これらのバイトに格納されている値を出力すると、値は 255 よりも大きくなります

しかし*rrrvoid *これはおそらくマシン上で 8 バイトであり、定義により任意のオブジェクト ポインターを保持できます。

また、 に 8 バイトしか割り当てていないためrrr、最初の要素を超えるもの (割り当てまたは読み取り) は無効です。


8 バイトを割り当てると、要素間で均等に分散されるという印象を受けているようですが、そうではありません。割り当て後、rrr使用できる 8 バイトを指し、*rrr = malloc.... これはすべて正しく、期待どおりです。これは*rrr空であるため、任意のアドレスを保持できるため、あなたが言及した 255 より大きいものを保持できます。

先に進むとrrr + 1、未定義の動作に足を踏み入れ、予期しないことが起こります。

編集

しかし、8バイトブロックの各バイト値を出力すると、どのバイトも値> 255を保持できるという点に異議を唱えます

しかし、あなたはバイトを印刷していません! ポインターを印刷し、追加irrr て次のポインターに進めます

于 2013-02-09T21:19:21.033 に答える
1

rrrは であるため、64 ビットの Linux マシン上で、割り当てた 8 バイト メモリに 40 バイトをポイントします void**rrr+5sizeof(void *) == 8

Cでポインタに整数を追加するときはいつでも、整数は常にポインタが指すもののサイズでスケーリング(乗算)されます(sizeof(*rrr)ここでは、これはですsizeof(void *)

于 2013-02-09T21:23:45.267 に答える