web-dev-qa-db-ja.com

charおよびchar *(ポインター)

ポインタがどのように機能するかを理解したいので、この小さなプログラムを作成しました。まず、charを指すpポインタを作成します。

最初の質問はこの時点です。ポインタを作成する場合、その値はメモリアドレスです(ポインタ以外のオブジェクトを指す場合)が、今回は私の例では「はは」です。なぜchar *でこのように機能するのですか?そして、どうすればcin >> pでそれに付加価値を付けることができますか?

2番目の質問は、q charを作成したことです。これは、作成した時点での* pポインターの値を持っています。しかし、その値とアドレスも「h」ですが、なぜですか?このcharオブジェクトのメモリアドレスである必要があります!それは無意味です:D(mingw --gcc)

#include <iostream>

int main() 
{
 /* char *p;
    cin >> p;                      //forexample: haha */

    char * p = "haha";
    char q = *p;
    std::cout << "&q = " << &q << std::endl;   //&q = h
    std::cout << "q  = " <<  q << std::endl;   //q = h

    return 0;
}

詳細:最初にchar a [100]でメモリを割り当てた場合。 char * p = a;次に&q = h"ŢĹなので、「h」といくつかの混乱。しかし、それはメモリアドレスでなければなりません!そして私の質問は、なぜそれが対処されないのですか?

7
Iburidu

_char* p;_をメモリ内のアドレスと考えてください。このポインタを初期化していないため、何も指していません。使用できません。

常に安全であるために:
ポインタをゼロに初期化する:

_char *p = 0; // nullptr in C++11
_

またはいくつかの自動に初期化します

_void foo() {
  char a[100];
  char *p = a;
}
_

またはグローバルメモリ:

_char a[100];
void foo() {
  char *p = a;
}
_

または動的メモリを取得します。

_char* p = new char [100];
_

次に、p(NULLでない場合)を使用してデータを読み取り、pから読み取ることができます...


operator >> (std::istream&, char* p)の誤解に対して。この演算子は、pが何らかのメモリ(自動、グローバル、動的-関係なく)を指していることを想定しています-それ自体ではメモリを割り当てません。入力ストリームから空白まで文字を読み取り、それをpが指すメモリにコピーするだけですが、pはすでに何らかのメモリを指している必要があります。


_char q;_のアドレスを取るため。もちろん、q:_&q_のアドレスを取ることができ、そのタイプは_char* p_です。ただし、_&q_はpとは異なり、この_q=*p_はpが指す最初の文字をqにコピーするだけで、qのアドレスを変更することはできません。そのアドレスは変更できません。 _cout << &q_の場合--operator << (ostream&, char* p)pがNULLで終了する文字列を指すことを期待します-そして_&q_は_"H"_を含むメモリを指しますが、この文字の後には誰も知らないので、画面にゴミが表示されます。 _cout << q_を使用して1文字を印刷します。

8
PiotrNycz

ポインタについて最初に学び、常に覚えておくべきことは、ポインタにメモリを割り当てることです。そうしないと、プログラムが正しく実行されません。

「cin」が割り当てられたメモリにユーザー入力を書き込めるように、実際には次のようにコードを変更してメモリを割り当てる必要があります。

int main() {
    char *p = new char[1024];      // allocate memory so cin
    cin >> p;                      //forexample: haha
    char q = *p;
    cout << "&q = " << &q << endl; 
    cout << "q = " << q << endl;   
    return 0;
}

ここで、文字ポインタは、文字のセットを保持するメモリ内の位置を指す変数です(必ずしも1文字である必要はなく、複数の場合もありますが、特別な値nullの場合のように、文字がない場合もあります)。単一の文字(文字のセットではありません)。

ポインタを扱うときの基本的な演算子は、&(のアドレス)と*(の値)です。 &は変数のアドレスを取得するため、[char q;]がある場合、[&q]は文字ポインターになります。一方、*は指定されたポインタの値を取得するため、[char * p;]がある場合、[* p]はpが指しているメモリ内の文字になります。

ここで例に戻り、説明のためにインラインでコメントします

int main() {
    // allocate a place of 1024 character in memory
    // and let p points to that place
    char *p = new char[1024];      

    // call cin to read input from the user and save
    // it in memory at the location pointed to by p
    // NOTE: cin would put an extra NULL character 
    // at the end to terminate the string
    cin >> p;                      //forexample: haha

    // Now p would be pointing to a piece of memory like this
    // [h] [a] [h] [a] [\0]

    // use the value at operator to de-reference the pointer
    // p, the result would be a single character which 
    // will be the first character in memory p is pointing at
    char q = *p;

    // printing the value of (the address of q)
    // Note you have a problem here as cout will
    // be handling the memory starting at the address 
    // of q as a string while it is not, so you
    // will get a string starting with "h" and followed
    // by whatever is there in memory by the time of execution
    cout << "&q = " << &q << endl;

    // printing the value of the character q
    cout << "q = " << q << endl; 
    return 0;
}

お役に立てば幸いです

3
Hisham

次のようなものが必要です。

#include <iostream>
using namespace std;

プログラムの上部にあります。または、usingを省略して、std::cinstd::coutを参照することもできます。

int main() {
    char *p;

pはポインタですが、まだ初期化されていないため、どこを指していても、どこを指していなくてもかまいません。たとえば、次のように初期化する必要があります。

p = new char[100];

.。

    cin >> p;                      //forexample: haha

これは問題ありませんifpをどこかを指すように初期化しました-ただし、入力するデータが多すぎる場合は、指すバッファをオーバーフローさせることができます。このような単純なテストプログラムでは問題ありませんが、実際には、それを回避するための対策を講じる必要があります。

    char q = *p;
    cout << "&q = " << &q << endl; //&q = h

&qのタイプはchar*で、charへのポインタです。 char*値をcoutに送信しても、ポインタの値(メモリアドレス)は出力されません。指している文字列を出力します。 (自分で実行すると奇妙な結果が得られますが、何かが足りない可能性があります。)ポインター値を確認したい場合は、void*にキャストしてください。

count << "&q = " << (void*)&q << endl;

(または、C++固有のキャストの1つを使用することもできます。どちらが最適かはわかりません。)

    cout << "q = " << q << endl;   //q = h

ここで、qは単なるcharであるため、その値を文字として出力します:h

    return 0;
}
1
Keith Thompson

それを行うためのより良い方法は次のとおりです。

    int arraySize;
    cin>>arraySize;
    char *a=new char[arraySize];
    cin >> a;
0
Nagendra Reddy

文字列literateは.rdataセクションに格納され、読み取り専用になるため、stdcinで読み取るとプログラムがクラッシュします。

あなたがこれを書くとき、2番目のこと:

char *p = "some text";

次に、ポインタpは、割り当てられた読み取り専用メモリを指します。これは、rdataセクションがWindowsローダーによって確実に割り当てられて準備されるためですが、前述したように、.rdataは変更できません。

それからあなたがこれを書くとき:

char q = *p;

*はポインタが現在指している値を返すので、pの最初の文字にqを割り当てるだけなので、これを試した場合:

++p;
q = *p;

ポインタは最初から始まるいくつかの文字を指すアドレスであるため、qは「a」ではなく「a」を保持します。したがって、1ずつ増やすと、ポインタは2番目の文字を指し、qはこの値を保持します。

0
dev65