-5

私は多くのプログラミング言語 (Java、Erlang、python など) をチェックしましたが、C/C++ を学ぶのは難しいと感じました。

例1:

    #include <iostream>

    int main() {

     int ar1 = {1,2,3};
     int *p1 = ar1;

     char *msg = "message";

     std::cout << "addr: " << p1 << std::endl ;//prints the array address

     std::cout << "value: " << *p1 << std::endl ;//prints the first element


     std::cout << "addr: " << msg << std::endl ;//prints "message" , wtf why not    the addr?how can i get its address?

     std::cout << "value: " << *msg << std::endl ;//prints the first character


    }

例2:

    #include <iostream>

    int main() {

     int n1 = 5;
     int *p1 = &n1;

     int &r1 = *p1; // why not: int &r1 = p1; ,*p1 is NOT an address,p1 is.This does not make any sense...



     }

これらの例を教えてください。これらを解決せずに Cplusplus の勉強を続けることはできません。

御時間ありがとうございます。

4

3 に答える 3

6

質問1:

char *msg = "message";
std::cout << "addr: " << msg << std::endl ;
//prints "message" , wtf why not    the addr?

これは、C からの言語の歴史的進化の成果物です。C では、文字列は従来、文字の配列またはそのような配列へのポインターによって表されます。これをサポートするために、 には を文字列へのポインタとして扱い、文字列の内容を出力する<<オーバーロードが含まれています。char const *

このクラスを使用して文字列を表すことで混乱を避けることができ、std::stringC スタイルの文字列が役立つ (非常にまれな) 状況を除き、C スタイルの文字列を避けることができます。

how can i get its address?

これを汎用ポインターに変換できます。

std::cout << "addr: " << static_cast<void*>(msg) << std::endl;
                         ^^^^^^^^^^^^^^^^^^

質問2:

int n1 = 5;
int p1 = &n1;

&n1はアドレスであるため、これはコンパイルされませんint。私はあなたが意味したと仮定します:

int *p1 = &n1;

int &r1 = *p1; 
// why not: int &r1 = p1; ,*p1 is NOT an address,p1 is.This does not make any sense...

参照はポインタではなく、アドレスで初期化されていないためです。参照は (有効な) オブジェクトで初期化する必要があり、そのオブジェクトのエイリアスになります。*p1は 型のオブジェクトであるintため、 への参照を初期化するために使用できますint

于 2012-07-20T15:51:47.917 に答える
2

問題の大部分は、あなたの例がほとんど間違っていることです。

最初の例:

 int ar1 = {1,2,3};
 int *p1 = ar1;

正しくは、これである必要があります。

int ar1[] = {1, 2, 3};
int *p1 = ar1;

この場合、物事は非常に単純です: ほとんどの状況 (これを含む) では、配列の名前はその配列の先頭のアドレス (つまり、ポインターに割り当てる値の型) に評価されます。主な例外は、配列を演算子のオペランドとして使用する場合ですsizeof。したがって、ポインターのサイズではなく、sizeof(ar1)配列の実際のサイズ ( ) が得られます。3 *sizeof(int)

あなたの2番目の例では:

 int n1 = 5;
 int p1 = &n1;

 int &r1 = *p1; // why not: int &r1 = p1; ,*p1 is NOT an address,p1 is.This does not make any sense...

その通りです。これは意味がありません。適切に機能するコンパイラは、そのままコンパイルするべきではありません。あなたが明らかに欲しいのは次のようなものです:

int n1 = 5;
int *p1 = &n1;   // p1 is a pointer to int, holding address of n1

int &r1 = *p1;   // r1 is a reference to int, referring to what p1 points at (n1).

出力に関する限り、それは非常に単純です: どのようなタイプが出力されるかは、ライブラリを書いた人々によって純粋に決定されます。彼らは、ポインタを char に渡すときに、指している文字列を出力したいと想定することが最も理にかなっていると判断しました。他のポインター型については、ポインター自体の値を出力することにしました。ただし、これは実際には言語自体に関するものではありません。それは、彼らにとって意味のあるものであったため、誰かが下した決定にすぎません。

char/char へのポインターの配列があり、そのアドレスが指す文字の代わりにアドレスを出力したい場合は、通常、それを void へのポインターにキャストします。

 char *msg = "message";

 std::cout << static_cast<void *>(msg);

彼らがこれを選んだ理由については、非常に単純だと思います。人々が と言うときcout << mystring、通常、文字列の内容を出力したいからです。文字列の内容を出力する方法については (ほぼ) 誰もが同意するため、通常は文字列に限定されますが、int や double などの配列の内容についてはそうではありません。

于 2012-07-20T15:56:04.467 に答える