3

と呼ばれるいくつかのポインタがあるとしましょう:

char * pChar;
int * pInt;

どちらも他の場所を指すメモリアドレスを保持するだけであり、型は特定のポインタが指すメモリの場所の大きさを宣言することを知っています。たとえば、char はシステム上の 1 バイトのサイズであり、int は 4 バイトである可能性があります。

pChar++; // I am actually incrementing the address pointed to by pChar by 1 byte;
pInt++; // I am actually incrementing the address pointed to by pInt by 4 bytes;

しかし、私がこれを行うとどうなりますか:

pChar+2; // increment the address pointed to by pChar by 2 bytes?
pInt+2; // increment the address pointed to by pInt by 2 bytes? what happens to the other two bytes?

ありがとう..ここで説明をいただければ幸いです..ポインタ型は単に ++ 操作のためですか?

編集: avp は私の質問に適切に答えましたが、フォローアップの質問があります。

memcpy(pChar,pInt,2);

2バイトコピーしますか?または4バイト?アクセス違反になりますか?

編集: Ryan Fox によると、答えは (void*) に型キャストされているため、2 バイトです。ありがとう!閉まっている!

編集:将来の検索者がこれを見つけることができるように..私が発見した別の情報..

memcpy(pChar+5,pInt+5,2);

pInt+5bytelocations が指すメモリ ブロックの 2 バイトを pChar+5bytelocations にコピーしません。2 バイトが pInt(4*5)bytelocations から pChar+5bytelocations にコピーされます。アクセス違反が発生したのも不思議ではありません。読んではいけないところを読もうとしていた.. :)

4

5 に答える 5

7

「++」は X = X + 1 の別名です。

ポインターの場合、1 ずつインクリメントするか N ずつインクリメントするかは問題ではありません。とにかく、sizeof(type)*N が使用されます。1の場合はsizeof(type)だけになります。

したがって、2 ずつインクリメントすると (2 番目のケース):
char の場合は 2*sizeof(char)=2*1=2 バイト、
int の場合は 2*sizeof(int)=2*4=8 バイトになります。

于 2008-12-19T09:11:13.223 に答える
5

ああ、今、私は理解しています。「型を持つポインターのポイントは何ですか?」と尋ねるべきでした。

実際には次の 2 つのポイントがあります。

  • ポインター演算;
  • 逆参照 (ポインターが指しているアドレスに格納されている値を取得する)。

どちらも、ポインターの型を知らなければ不可能です。

追加: memcpy のドキュメントを読みます。memcpy はポインタの型がわからないため、最後の引数はバイト数です。それへの両方の引数は void ポインターです。

追加 2:アクセス違反 - 依存します。これらのポインターに割り当てたメモリの外に出ない場合、アクセス違反は発生しません。コピー操作はすべてをバイト単位でコピーし、期待どおりの結果を取得します (あまり意味がないかもしれませんが)。

割り当てられたメモリの境界を超えると、アクセス違反が発生する可能性がありますが、別の変数に割り当てられたメモリにクロスオーバーする可能性があります。プログラムが実行されたときに何がどこにあるのかを知ることはほとんど不可能です。


ポインターには、主に次の 3 つの利点があります。

  1. 「参照によって」関数に引数を渡すことができます。これは、C++ のような実際の参照を持たない C でより大きな問題でしたが、外部ライブラリと連携する必要がある場合など、多くの場合に依然として非常に役立ちます。また、参照渡しが役立つのは、渡す変数を関数で変更する場合だけではありません。また、大きなデータ構造をパラメーターとして渡すのにも非常に適しています。
  2. ツリー、リンクされたリストなど、あらゆる種類の気の利いた動的データ構造を構築するため。これはポインターなしでは不可能です。
  3. 必要に応じて、配列をより大きな/より小さな配列に再割り当てできるようにするため。

PS質問は、算術を例としてのみ使用して、ポインターが優れている理由についてだったことを理解していますよね?

于 2008-12-19T09:16:15.570 に答える
3

ポインター演算は、正確にはそのようには機能しません。あなたの最初の例は正しいですが、2番目の例はそれほどではありません。

pChar+2; // increment the address pointed to by pChar by 2 bytes
pInt+2; // increment the address pointed to by pInt by 8 bytes
于 2008-12-19T09:12:01.380 に答える
1

この部分について:

memcpy(pChar+5,pInt+5,2);

最初に "+" が評価され、次に型キャストされます。

したがって、バイト単位で:

pChar+5 ここで "5" は 5 バイト、
pInt+5 ここで "5" は 5 int なので、5 * 4 = 20 バイトです。
次に、すべてが void* にキャストされ、2 バイトがコピーされます。

「5」の代わりにカウンターを使用する場合は、次のようになります。

for (int i = 0; i<100; i++)
    memcpy(pChar+i, pInt+i, 2);

次に、pChar の場合、コピーされた 1 バイト (2 番目) を次のコピー コマンドで上書きします。pInt の場合、各ステップで 4 バイトずつジャンプします (ただし、int の配列では問題ありません)。

于 2008-12-19T13:57:31.457 に答える
0

C++でのポインター型のポイントは、vtable のオフセットを考慮することだと私は言ったでしょう。

于 2008-12-19T10:23:48.507 に答える