2

さて、ポインタ配列について読んだ私の理解から:

配列は、インデックス付きの各要素を指すため、定数ポインターと同等と見なされます。また、配列へのポインターは、最初のインデックスのアドレスと同等です。

まあ-これは有効なので:

int test[] = {1, 2, 3}

int * point = test;

cout << test + 2; //gives the address of the 3rd element test[2]

私は疑問に思っていましたが、なぜこれは異なる動作をするのでしょうか?

char arr[] = "testing pointer arrays";
char * pointer = arr;
cout << pointer + 3 << endl; //would output the actual string at pos arr[3]

同様に:

char * test = "zomg";
cout << test + 2; //outputs mg

この場合、char ポインターは本当に特別なのでしょうか? ストリーミング用の関数で、ポイントをインクリメントしてサイズを指定することで、書き込み/読み取りができるバイト数を指定する方法に関する別の質問に私を導きます (ofstream::write(char pointer, size); のように)さらに、構造体を文字ポインタに型キャストすると、それをバイト配列に変換できますか?

明確化していただければ幸いです、ありがとう。

4

3 に答える 3

2

これ

char arr[] = "hello";

と同等です

char arr[] = {'h', 'e', 'l', 'l', 'o', '\0'};

唯一の違いは、 のような文字列リテラルの意味であり、"hello"の配列がchar他の組み込み型の配列と比較して扱われる方法ではありません。

次に、 to を渡すchar*std::cout

std::cout << pointer + 3 << endl;

ポインタを null で終わる文字列の最初の要素として扱うostream& operator<<forの特別なオーバーロードがあるという事実から恩恵を受けます。char*

于 2013-05-26T14:58:59.660 に答える
1

これは、C (および C++ の歴史的な理由による) では、ほとんどの場合、char へのポインターは、文字で終了する char のシーケンスへのポインターNUL( として記述'\0') と見なされるためです。

たとえば、 を受け入れる C++ 関数があるstd::string場合、ポインタを char に渡すこともできます。これは、言語が C 文字列 (つまり、 で終了する char のシーケンスNUL) と標準 C++ 文字列から暗黙的な変換を行うことを想定しているためです。

出力演算子は同じことを行うため、送信するときに、test+2代わりにそこから始まる C 文字列を本当に出力したいと想定します。

于 2013-05-26T15:09:20.003 に答える
0

インデックス付きの各要素を指しています。

配列について重要なことを忘れています。配列は、メモリ内の連続した領域に割り当てることが許可されているデータ構造であり、各レコードに同じタイプのデータが含まれています。配列の定義を考えると、それが配列の開始点と終了点であることを本当に知る必要がある唯一のことであり、配列内のすべてのレコードを指す必要はありません。任意の配列の始まりと終わり。

あなたの例

int test[] = {1, 2, 3}

int * point = test;

cout << test + 2; //gives the address of the 3rd element test[2]

それはあなたにそれを示していますが、初心者にとってはより不可解な方法です.

testサイズ[]が指定されていない配列ですが、要素の有限リストを取得したため、コンパイラはtest3 つの要素 (3 int) にスペースを割り当てるのに十分なほどスマートであり、配列testが作成されます。

int * point = test;ここでは、配列の最初の要素、つまり配列が始まる場所を指すテストがあります。pointこれは int へのポインターであり、アドレスはまさにポインターにフィードできるものであるため、ここにエラーはありませんただし、ここでは配列のラベルを使用して配列の開始アドレスを渡していることに注意してくださいtest

つまりtest[0]、配列の最初の値である値を提供し、配列test全体のアドレスを提供します。

test + 2これは単なるアドレスのプレースホルダーであることがわかりtestます。単純に 2 を足すだけです。その結果、2 つの位置をスキップして 3 番目の値がある場所に直行しますが、常にメモリ内のアドレスに関してではなく、保存された値の観点から。

この最後の演算はポインタ演算の例であり、基本的には単純な数値で行われる論理演算です。実際、配列はメモリ内の 1 つの連続したブロックにすぎないため、+1 または -1 を数えるだけで次の値に到達できます。または前の値、あなたの問題は、配列の実際の境界チェックがないことです。そのため、他のものの一部であるメモリアドレスに到達するほど上下することさえあります。

ポインター演算に関する簡単な例があります

#include <stdio.h>

int main()
{
  int k[] = {34,765,23,5,7,123,8,99};
  int j = 3;

  printf("\nfirst print is  %d \n",k[j]);
  printf("\nsecond print is %d \n",j[k]);

  return(0);
}

ポインター演算について知っておく必要があるのはこれだけです。自動化された境界チェックがないことを覚えておいてください。すべてはあなたの手の中にあります!

于 2013-05-26T15:16:12.353 に答える