CCS C コンパイラのコードを理解できません。コードは次のとおりです。
addr[0] = *(((char*)&block_number)+2);
&block_number
「 」は「block_number」という名前の変数のアドレスだと思います。その後、私は迷子になります。
CCS C コンパイラのコードを理解できません。コードは次のとおりです。
addr[0] = *(((char*)&block_number)+2);
&block_number
「 」は「block_number」という名前の変数のアドレスだと思います。その後、私は迷子になります。
block_numberが何であるかわからない場合、言うのは少し難しいです。値が次の整数であるとしましょう0xdeadbeef
:
unsigned int block_number = 0xdeadbeef;
リトルエンディアンアーキテクチャ(つまりx86):
*(char *)&block_number is 0xef,
*(((char *)&block_number) + 1) is 0xbe and
*(((char *)&block_number) + 2) is 0xad.
block_numberがchar
thenの場合*(((char *)&block_number) + 2)
、隣接する変数を指すことができますが、block_numberがスタックで宣言されているとします。
char a = 0xab, b = 0xbc, block_size = 0xcd, c = 0xde, d = 0xef;
次に、ieを((char *)&block_size + 2
指すことができ、を返します。スタックは通常、最大アドレスから下位アドレスの順に並べられているため、次のようになります。a
*(((char *)&block_size + 2)
0xab
heap stack
[... -> <- d | c | block_size | b | a ]
[... -> <- 0xef | 0xde | 0xcd | 0xbc | 0xab ]
しかし、Cはコンパイラーに場所を制限せずa
、場所はおそらく未定義であるため、これは決して確実ではありません。
それsizeof(char)
は常に 1
です。char
は1文字です。そのため、メモリを割り当てる場合は、mallocにlength * sizeof(char)を指定する必要はありません。あなただけがします:
int length = 20;
void *mem = malloc(length);
これを分割しましょう:
*(ptr+2)
次と同等です。
ptr[2]
ここで、ptr
はchar*
のアドレスを指していますblock_number
。
つまりblock_number
、次のような構造体のインスタンスです。
struct {
char a;
char b;
char c;
char d;
} block_number
次にaddr[0]
、の値が含まれますc
(値の間にスペースがなくパックされていると仮定します)。これは、へのポインターblock_number
が に変換されchar*
、配列のようにインデックス付けされるためです。
基本的に、これは の 3 番目のバイトを読み取りますblock_number
。
&block_number
オブジェクトのアドレスですblock_number
。
(char*)&block_number
そのアドレスをバイト配列の最初の要素のアドレスとして扱います。このポインタを と呼びましょう。p
これは へのポインタchar
です。
*(((char*)&block_number)+2)
したがって*(p + 2)
、 は と同じですp[2]
。つまり、配列の 3 番目の要素を示します。
つまり、オブジェクトのバイナリ表現の 3 番目のバイトを取得していますblock_number
(そしてそれを保存していますaddr[0]
)。
あなたは正しいです。&block_number はその変数のアドレスで、char にキャストされ、値に 2 が追加されます。たとえば、&block_number が 0x0000 の場合、プラットフォームの sizeof(char) が 2 の場合、またはサイズが何であれ、行を実行した後の addr[0] には 0x0002 が含まれます。