2

私は型キャストを行っintcharが、ポインターを使用しなかったので、この質問を投稿しました。

#include <stdio.h>
int main() {
    int a[4] = { 1, 2, 6, 4 };
    char *p;
    p = (char *)a;   // what does this statement mean?
    printf("%d\n",*p);
    p = p + 1;        
    printf("%d",*p);  // after incrementing it gives 0 why?
}

を最初に呼び出すとprintf、配列の最初の要素が返されます。そしてp=p+1それが与えた後0。なんで?

4

6 に答える 6

5

1 バイトが 8 ビットで、メモリがリトル エンディアンのバイト順で配置され、intがメモリ内の 4 バイトを表す、かなり典型的なプラットフォームを想像してみましょう。このプラットフォームでは、値は次の1ように配置されます。

00000001 00000000 00000000 00000000
^
the first element of 'a'

pcharは(notへの) ポインターとして宣言されint、 array の最初の要素を指すように初期化されaます。charこのプラットフォームの Aは 1 バイトを表します。intとして解釈された上記の値は次のcharようになります。

00000001 -------- -------- --------
|      |
 ------
 char is only 8 bits wide

したがって、1 バイトを読み取っても 4 バイトを読み取っても、つまり を読み取っても を読み取って*pa[0]、値は1です。pただし、へのポインタであるをインクリメントすると、メモリ内charの次の文字、つまり次のバイトを指すようになります。

00000001 00000000 00000000 00000000
00000001 00000000 -------- --------
^        ^        ^        ^
p       p+1      p+2      p+3       ...

a[1]は次のint( 2) をp[1]指し、次のchar、つまり を指し0ます。


余談ですが、特定のプロセッサがリトル エンディアンまたはビッグ エンディアンのバイト順を使用しているかどうかを判断する方法を実際に見つけました。システムがビッグ エンディアン (最上位バイトが最初) の場合、最初printfに 0 が出力されます。これは、メモリ レイアウトが変更されたためです。

0000000 00000000 00000000 00000001
^
the first element of 'a'

0000000 -------- -------- --------
^
p

値 1 を表すビッグエンディアン順に配置された複数のバイトがあり、最初のバイトのみを読み取る場合、その値 (1または0) を使用してマシンのエンディアンをテストできます。

int n = 1;
if(*(char*)&n == 1)
    // little endian
else
    // big endian
于 2012-08-05T07:27:32.717 に答える
2

正確にはprintf、最初の要素は配列の最初の要素を与えるのではなく、最初の要素の最初の8 ビットを与えます。これはたまたま最初の要素の数値に等しくなります。2 番目の printf は、最初の要素の次の 8 ビット (この場合は 0) を提供します。

1 = 00000000 00000000 00000000 00000001 (32 ビット)

于 2012-08-05T07:09:08.330 に答える
2

4 つの整数の配列があります。文字の「配列」としてそれらにアクセスしようとします。それがキャスティングの意味です。

2 番目のprintf印刷ゼロについては、整数は 4 バイトですが、文字は 1 バイトであることに注意してください。そのため、ポインターpを増やすpと、最初の整数の 2 番目のバイト (ゼロ) を指すようになります。より大きな数 (つまり 255 以上) の場合、2 番目のバイトにも値が含まれます。ただし、これはリトル エンディアンのIntel タイプのマシンでのみ機能することに注意してください。ビッグ エンディアンのマシンでは両方ともprintfゼロが出力されます。

于 2012-08-05T07:10:43.070 に答える
1
int a[4] = { 1, 2, 6, 4 };

を配列として宣言します。aこの時点で、配列の最初の要素のアドレスが格納されます。

char *p;

p をpointertoとして宣言しますcharacter

p = (char *)a;

今以来p&a両方の店舗の住所. したがって、a(address配列の最初の要素の) に格納されているアドレスが に割り当てられpます。型キャストは、次のようpに宣言されたとおりに行われますchar *

それが行うことは、格納されているアドレスaが100であると仮定し、それintが2バイトをchar取り、メモリ内で1バイトを取ると仮定することです

a+1 would return a+size of int(2) = 102

p+1 would return p+size of char(1) = 101 

そして、それは出力を次のように説明します

A. 格納されている 2 バイトaには、配列の最初の要素が含まれています。

B. に格納されpている 1 バイトは、整数の最初のバイトの文字表現1です0

お役に立てれば。

于 2012-08-05T07:16:03.087 に答える
0

Intel のようなプロセッサを使用する場合、スタック上のバ​​イトはリトル エンディアン形式を使用して格納されます。さらに、おそらくタイプ int (コンピューター上) のサイズは 4 バイトですが、char の長さは 1 バイトです (これは、c 演算子 'sizeof' を使用して確認できます)。したがって、整数配列の最初の要素は次のようになります。

0x04 0x00 0x00 0x00

このため、整数配列の値を参照するために char ポインターを使用する場合、得られた明らかな結果とともに (4 ではなく) 1 バイトずつ前方に進みます。

これが役立つことを願っています!

于 2012-08-05T07:19:53.587 に答える
0

a はメモリ配列へのポインタです。このメモリは、16 バイトの連続したブロックとしてリトル エンディアンの 2 の補数形式で配置されている可能性があります。

キャストすると、基本的に「これはintの配列へのポインターであることはわかっていますが、データをcharの配列として再解釈します」と言っただけです。char は通常 1 バイトです。したがって、ポインターに 1 を追加すると、ポインターが指す場所がインクリメントされます。これは char 配列であるため、0 を含む int の中間にある配列を1バイト下に進めました。

明確にするために、あなたのコンピューターのアーキテクチャについて私が想定していることに基づいて:

リトルエンディアン数(最も有意なバイトが最初に来る):
0000000100000000000000000000 in binary = 1 in decimal 0000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011001000000000000000000000000000 inバイナリ= 6 decimal 000001000000000000000000000000000000000000

int の配列は次のようになります。

0000010000000000000000000000000000000000001000000000000000000000000100000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

変数 "a" は、32 ビットの最初の整数を指します (つまり、"*a" は です00000001000000000000000000000000)。変数 "a" に 1 を追加すると、ポインターがインクリメントされるため、 *(a+1) は 2 番目の int を指し00000010000000000000000000000000ます)。

ここで、変数 "a" を "char*" ポインターにキャストします。したがって、変数 "p" は同じ場所を指しますが、これは char ポインターであるため、8 ビットの最初の char を指します (つまり、"*p" は00000001配列の最初のバイトです)。

最後に、「p」をインクリメントすると、ポインタがインクリメントされます。"p" は chars へのポインターなので、1バイト進みます。したがって、"*(p+1)" は00000000.

于 2012-08-05T07:23:02.167 に答える