C/C++のポインタの機能--変数の場所(アドレス)

沖林正紀
2008-03-27 17:00:00
  • このエントリーをはてなブックマークに追加

ポインタとは

 ポインタはC/C++言語の特徴的な機能のひとつである。ポインタ(pointer)を直訳すると「指し示すもの」であり、別の変数や文字列定数の場所を指し示すために使う。また、ポインタを指すポインタ(ポインタへのポインタ)というものも存在する。

 このページをお読みいただいている読者にあっては、「C言語 ポインタ」「C++ ポインタ」などのキーワードでWeb検索をしたことがあるかもしれない。そうするとポインタに特化した内容の書籍をいくつか見つけられる。それだけ奥が深い機能ということである。

ポインタの用途

 では、ポインタはどんなところで使われているのだろう。C/C++言語では、あらかじめ定義されている関数が多数存在するが、その一覧には、*(アスタリスクあるいはアステリスク)が付いているものをよく見かける。

 これらはポインタを表し、主に文字列の操作やファイルをはじめとするデータの入出力を行う関数において、ポインタの機能を利用することを表している。とくにC言語では呼び出し元の変数を変更する「参照呼出し」という機能がないため、C言語に由来する関数ではポインタを使用することが多い。

ポインタ変数の定義

 ポインタ変数を定義するには、通常の型の場合とは異なり、型名の後ろに * がつけられる。以下はint(整数)型へのポインタとして、pという変数を定義する例である。ここでは、まずint型の変数nを定義する(初期値は5としておく)。nという変数の場所(アドレス)は&演算子(アドレス演算子)で取得できるので、これをpというポインタ変数の初期値として使っている。pのデータ型はint *、つまり整数値へのポインタ型となる。pが指し示す値は*を変数の直前につけて*pとすれば得られる。このときの、*pはint型である。pが指し示しているのは変数nの場所であり、ここでは、その場所にある値(変数nの中身)は5なので、*pは5になる。

ソースコード1

    int n = 5;    /* 通常の変数 n の定義(初期値は5) */
    int *p = &n;  /* ポインタ変数pの定義(初期値はnのアドレス) */

 続いて、ポインタを使って値を代入する例を示す。このときpには変数nの場所(アドレス)が代入されているため、*p に値を代入することは、変数nの値を変更することと同じである。たとえば、次のように*pに10を代入すると、変数nの値が10になる。

ソースコード2

   #include 

    int main( void ) {
      int n = 5;
      int *p = &n;
      *p = 10;   /* ポインタ変数を使って値10を代入 */
      printf( "%d\n", n );  /* 変数nの値を出力(10が表示される) */
      return 0;
    }
  • コメント(28件)
#1 prometheus   2008-03-27 21:46:12
>ポインタ変数に値を代入し、それを出力する例を示す
 ポインタnはどこを指しているのでしょうか?
#2 mohno   2008-03-28 03:12:43
すでに指摘されていますが、筆者の方はポインタを理解されていないと思います。
「参照渡し」も実際にはポインタを値で渡しているのですし、&を使って変数をポインタ変数に変えたりできるのではありません。
#3 tomita   2008-03-28 18:57:30
builder編集部 冨田です。

prometheusさん、mohnoさん、コメントありがとうございました。
著者の沖林さんからは、

「 ご指摘をいただいた賢明な読者の方々に感謝します。
表現が短絡的に過ぎ、結果として読者の方々に誤解を
与えてしまったのかもしれません。 」

とのコメントを頂きました。

また、沖林さんと編集部で相談し、記事を下記のように修正しました。

タイトル「C/C++のポインタの機能--参照渡し」

タイトル「C/C++のポインタの機能--参照渡しののような処理」

1ページ目
見出し「ポインタ変数の宣言」の個所

「ポインタ変数を宣言する例を以下に示す。一般の変数の場合とは異なり、名称の先頭に*がつけられる。このポインタ変数が持つ値のデータ型はintだが、それ以外のデータ型でポインタ変数を宣言することもできる。」

「ポインタ変数の宣言では、一般の変数の場合とは異なり、名称の先頭に*がつけられる。以下はnというポインタ変数を宣言する例である。ここでは、*nが表す値のデータ型はintとなるが、それ以外のデータ型でポインタ変数を宣言すれば、*nはその型の値を表すことになる。」

「ポインタ変数に値を代入し、それを出力する例を示す。*nは一般の変数と同じように用いることができるのがお分かりいただけるだろう。」

「*nを使って処理に用いる値を代入し、それを出力する例を示す。このときnには代入された値を記憶した場所(アドレス)が自動的に代入されるため、nそのものの値は実行されるごとに異なる可能性があるものの、*nが表す値は、処理中に変更されない限り5のままである。」

2ページ目
見出し「ポインタ変数の特徴」の個所

「2. 一般の変数を一時的にポインタ変数に変えることもできる」

「2. 一般の変数からもアドレスを参照できる」

見出し「1. 変数には複数の記述方法がある」の個所

「つまり、*nはアドレスを介してプログラムで用いる値を参照していることになる。そのため、このような処理を参照渡しという。」

「つまり、*nはアドレスを介してプログラムで用いる値を参照していることになる。C/C++においては、このようにアドレスの値を用いることで、参照渡しのように機能させることができるようになっている。」

「2. 一般の変数を一時的にポインタ変数に変えることもできる」

「2. 一般の変数からもアドレスを参照できる」

「このとき&nは、一般の変数nを一時的にポインタ変数に変えていることを表している。このようにすることで、一般の変数でも参照渡しをできるようにしているのだ。」

「この&nは、一般の変数nを用いて、その値が記憶されている場所(アドレス)を参照していることを表している。このときの&はアドレス演算子と呼ぶ。」


以上です。貴重なご意見、ありがとうございました。
今後もどしどしコメントを付けていただければ幸いです。
#4 tomita   2008-03-28 20:17:25
著者の沖林さんから読者の皆様へメッセージが届いております。

「賢明な読者の方々に対し、まずは感謝の意を表します。
ご指摘を元に記述を見直しましたが、至らないところが
あれば、今後とも引き続きご指導願いたく存じます。
改めて、本稿の賢明な読者の方々に感謝申し上げます。 」

今後も忌憚のないご意見・ご要望をお聞かせ下さい。
#5 επιστημη   2008-03-28 23:52:28
文面はともかくも、最初のコード:
  int *n;
 *n = 5; /* ポインタ変数nに値5を代入 */
これをなんとかしないと。
とてつもなく危険なコードですから。

やりたいことがコメント通り "ポインタ変数nに値5を代入" なら
 n = 5;
じゃないとおかしいし。
#6 επιστημη   2008-03-29 00:14:27
[2page冒頭]
>  プログラム内で用いる値は*nでを示しているのだが、nが示しているのは、
> その値を記憶させるメモリ上のアドレスだ。それ自体は自動的に設定されるため、
> 開発者が具体的なアドレスを設定する必要はない。

これまたとんでもない。
「自動的に設定される」んじゃなく「どこを指すかはまったく不定」です。
実行したとたんにマシンから煙が上がっても文句いえません。
「具体的なアドレスを設定する必要はない」じゃなく「具体的なアドレスを設定しなければならない」です。まったく逆。
#7 Jitta   2008-03-29 07:27:04
まず、ポインタ変数がなぜ必要なのか。Java や C# では取っ払ってしまったポインタ変数とはなんぞや?そこが必要ではないでしょうか。
著者さんのお名前を検索すると Java 関係の著書がありますね。Java から入ったから、Java で隠蔽されたポインタがなぜ必要なのか、なぜ Java では隠蔽されたのか、理解が及んでいないのではないでしょうか。

2ページ目。
> 先ほどまで*nと記述してきたポインタ変数は、宣言以降はnという記述も許される。
許されません。
scanf がアドレスを期待しているので、scanf に引き渡す変数はアドレスを指すようにします。printf は値を期待しているので、printf に引き渡す変数は値を指すようにします。「記述も許される」訳ではありません。
どういう動きをするから、何を渡さなければならないのか。きちんと決まっています。
この説明では、まぜこぜに使う人が現れそうで怖いです。

おそらく、初学者向けの記事であると思います。難しい概念を適当にはしょって説明し、ある程度知識や考え方が身についてから、改めて説明し直す、ということがあってもいいと思いますし、実際そういう説明もします。そうであったとしても、特に2ページ目は、適切な説明であるとは思えません。
#8 chaos   2008-03-29 10:39:50
ん~...この20年で、最低最悪のポインタの説明だ...
・すでにポインタがわかっている/わかっているつもりの人が、この記事の間違いを探すというテスト問題としてはまずまずかもしれない。
・既に身についていて後輩に教える立場の人が、ポインタが分からない人はこういう誤解をするものなのだというサンプルとしては役にたつかもしれない。

ですが、初心者は混乱するだけで、絶対に読んではいけないと思います。

あまりに惨いので、このコメントを書くために、CNET_IDを取得しました。
記事訂正どころか、とりあえずは一旦、削除すべきだとすら思います。
#9 tomita   2008-03-30 12:52:17
builder編集部 冨田です。

1ページ目 最下段のソースですが、下記(1)のように記述しておりました。
しかしこれ、「」を文字実体参照として記述していないため、
一部ソースが表示されておりませんでした。修正後のソースが(2)となります。
(1)
    #include 

    int main( void ) {
      int *n;
      *n = 5;   /* ポインタ変数nに値5を代入 */
      printf( "%d\n", *n );  /* ポインタ変数nが持つ値(5)の出力 */
      return 0;
    }

(2)
    #include 

    int main( void ) {
      int *n;
      *n = 5;   /* ポインタ変数nに値5を代入 */
      printf( "%d\n", *n );  /* ポインタ変数nが持つ値(5)の出力 */
      return 0;
    }
#10 tomita   2008-03-30 12:57:13
同じく2ページ目のソース2点についても、上記と同様のミスがありました。
最初のソースの修正前(1)、修正後(2)、2番目のソースの修正前(3)、修正後(4)として
下に記します。
では、引き続きよろしくお願いいたします。
(1)
    #include 

    int main( void ) {
      int *n;
      scanf( "%d", n );      /* *nの値をキーボードなどから入力(Enterで終了) */
      printf( "%d\n", *n );  /* nの値を出力 */
      return 0;
    }

(2)
    #include 

    int main( void ) {
      int *n;
      scanf( "%d", n );      /* *nの値をキーボードなどから入力(Enterで終了) */
      printf( "%d\n", *n );  /* nの値を出力 */
      return 0;
    }

(3)
    #include 

    int main( void ) {
      int n;
      scanf( "%d", &n );     /* nの値をキーボードなどから入力(Enterで終了) */
      printf( "%d\n", n );   /* nの値を出力 */
      return 0;
    }

(4)
    #include 

    int main( void ) {
      int n;
      scanf( "%d", &n );     /* nの値をキーボードなどから入力(Enterで終了) */
      printf( "%d\n", n );   /* nの値を出力 */
      return 0;
    }
#11 がる   2008-03-30 16:15:09
がると申します。
んと…修正した後もなおおかしいソースのまま、というのは、非常に好ましくないと思うのうですが。
最低限、付記ように修正される方がよろしいのではないかと思うのですが如何なものでしょうか?

あまりにも気になりましたので、一筆。
1page
    #include 

    int main( void ) {
      int *n;

      int i;
      n = &i;

      *n = 5;   /* ポインタ変数nに値5を代入 */
      printf( "%d\n", *n );  /* ポインタ変数nが持つ値(5)の出力 */
      return 0;
    }

2page
    #include 

    int main( void ) {
      int *n;

      int i;
      n = &i;

      scanf( "%d", n );      /* *nの値をキーボードなどから入力(Enterで終了) */
      printf( "%d\n", *n );  /* nの値を出力 */
      return 0;
    }
#12 Jitta   2008-03-30 22:07:07
ポインタ変数として宣言すると言うことは、「この変数は、入れ物のありかを示しますよ」という宣言をするということです。従って、

int *n;
*n = 5;

とすると、「n は、入れ物のありかを示しますよ。でも、その場所はまだ指定しません。その場所に 5 を入れてください」という意味になります。では、5 は、どこにはいるのでしょうか。
という指摘が、コード訂正前にされている訳ですが、3/30 12:52 の修正で訂正されていないのはなぜでしょう?
記事の推薦が、今現在で20人の方から行われていますが、これは「反面教師として」ですよね?

「このときnには代入された値を記憶した場所(アドレス)が自動的に代入されるため、nそのものの値は実行されるごとに異なる可能性があるものの、*nが表す値は、処理中に変更されない限り5のままである。」

「このとき、nは代入される値を記憶するべき場所を示す値として宣言される。この場所は、プログラマが明示的に指示しなければならない。指示する場所は、mallocなどのメモリ確保関数によって確保するか、他の変数が使っている場所を指示する。宣言によって示されている場所は、処理系によって異なるが、プログラムがアクセスしては行けない場所を示していることもある。そういう場所に書き込むと、プログラムが異常終了することになる。また、プログラムが書いてある場所を指している場合もある。この場合、プログラムが思いもよらない処理をする場合がある。バッファオーバーランという脆弱性は、この用にして発生する。」

今の説明では、バッファオーバーランの危険性を多分に含んでいます。早期に訂正してください。

「C/C++においては、このようにアドレスの値を用いることで、参照渡しのように機能させることができるようになっている。」
対象読者は、Javaなどに精通していることが前提ですか?
確かに、Javaなどの言語に精通している人にはこれで通じるでしょうが、C/C++から始めようとしている人、VBから移行組でも、これでは通じないのではないでしょうか。
#13 mrkn   2008-03-31 03:12:36
επιστημη さんもご指摘されていることですが,
int *n;
*n = 5;
このようなコードが何故なんのチェックもされないまま公開されているのでしょう?
これだけではありません.その下に出てくる
int *n;
scanf( "%d", n ); /* *nの値をキーボードなどから入力(Enterで終了) */
printf( "%d\n", *n ); /* nの値を出力 */
こちらも早く***コメントではなく本文の方で***なんとかしてもらいたいです.

著者は別の記事でも scanf でバッファオーバフローの可能性があるコードを示していたり,
配列とポインタの違いを理解していないなど,C の解説を書けるだけの知識を持っていない
事は明白ですが,著者以外にこのサイトの編集者はチェックしていないのでしょうか?
たとえ C が分からなくても,コンパイルして実行してみれば分かることですよね.

さらに,コメント欄で修正内容が補足されていますけど,
> このときnには代入された値を記憶した場所(アドレス)が自動的に代入されるため
これは何人もの方が指摘されている通り間違ってますよね.一刻も早く
***コメントではなく本文の方で***修正してください.

私は高専,専門学校で講師をしています.このような嘘を教える内容の解説記事が
Web 上で公開されてしまいますと,多くの学生に悪い影響を与えることになってしまいます.
C が分からないなら C の解説記事は書かないでください.
一刻も速く修正されるか,記事自体が消去されることを望みます.
#14 chie65536   2008-04-01 13:40:24
この筆者は「ポインタ変数は、宣言したら、すぐに参照に使える。そのポインタがどこを指してても構わない」と思っているに違いない。

誰か、この筆者に「ポインタ変数は、宣言しただけでは、すぐには使えない。どこか、値そのものを入れる『実体』を用意し、ポインタがその実体を指すように初期化してから、ポインタ参照を行う」って教えてあげて下さい。

そして、誰か、この編集者に「人選を誤った」って教えてあげて下さい。
#include 
int main( void ) {
    int *n;
    int i[1];   /* 値を格納する実際の場所 */
    n = i;   /* ポインタ変数nを、iを指すように初期化 */
    *n = 5;   /* ポインタ変数nが指す先、つまりiに値5を代入 */
    printf( "%d\n", *n );  /* ポインタ変数nが指す先が持つ値(5)の出力 */
    return 0;
}
#15 tomita   2008-04-01 15:23:46
builder編集部 冨田です。
4月1日 15時に本稿の1ページ目を修正しました。修正個所は下記の通りです。

タイトル
「C/C++のポインタの機能--参照渡しのような処理」

「C/C++のポインタの機能--変数の場所(アドレス)」

見出し「ポインタとは」の項

第1段落
「 ポインタはC/C++言語の最も特徴的な機能といえるもので、ポインタ変数と呼ばれるもので操作する。ポインタ変数の配列を宣言することもできる。また、多次元配列のように、ポインタのポインタというものも存在する。」

「 ポインタはC/C++言語の特徴的な機能のひとつである。ポインタ(pointer)を直訳すると「指し示すもの」であり、別の変数や文字列定数の場所を指し示すために使う。また、ポインタを指すポインタ(ポインタへのポインタ)というものも存在する。」

見出し「ポインタの用途」の項

第1段落
「 では、ポインタはどんなところで使われているのだろう。C/C++言語では、main以外にあらかじめ利用可能になっている関数が多数存在するが、その一覧には、*(アスタリスクあるいはアステリスク)が書かれているものをよく見かける。」

「 では、ポインタはどんなところで使われているのだろう。C/C++言語では、あらかじめ定義されている関数が多数存在するが、その一覧には、*(アスタリスクあるいはアステリスク)が付いているものをよく見かける。」

第2段落
「 これらはポインタ変数を表し、主に文字列の操作やファイルをはじめとするデータの入出力を行う関数において、ポインタの機能を利用することを表している。」

「 これらはポインタを表し、主に文字列の操作やファイルをはじめとするデータの入出力を行う関数において、ポインタの機能を利用することを表している。とくにC言語では呼び出し元の変数を変更する「参照呼出し」という機能がないため、C言語に由来する関数ではポインタを使用することが多い。」

見出し「ポインタ変数の宣言」

見出し「ポインタ変数の定義」の項

第1段落
「 ポインタ変数の宣言では、一般の変数の場合とは異なり、名称の先頭に*がつけられる。以下はnというポインタ変数を宣言する例である。ここでは、*nが表す値のデータ型はintとなるが、それ以外のデータ型でポインタ変数を宣言すれば、*nはその型の値を表すことになる。」

「 ポインタ変数を定義するには、通常の型の場合とは異なり、型名の後ろに * がつけられる。以下はint(整数)型へのポインタとして、pという変数を定義する例である。ここでは、まずint型の変数nを定義する(初期値は5としておく)。nという変数の場所(アドレス)は&演算子(アドレス演算子)で取得できるので、これをpというポインタ変数の初期値として使っている。pのデータ型はint *、つまり整数値へのポインタ型となる。pが指し示す値は*を変数の直前につけて*pとすれば得られる。このときの、*pはint型である。pが指し示しているのは変数nの場所であり、ここでは、その場所にある値(変数nの中身)は5なので、*pは5になる。」

第2段落
「 続いて、*nを使って処理に用いる値を代入し、それを出力する例を示す。このときnには代入された値を記憶した場所(アドレス)が自動的に代入されるため、nそのものの値は実行されるごとに異なる可能性があるものの、*nが表す値は、処理中に変更されない限り5のままである。」

「 続いて、ポインタを使って値を代入する例を示す。このときpには変数nの場所(アドレス)が代入されているため、*p に値を代入することは、変数nの値を変更することと同じである。たとえば、次のように*pに10を代入すると、変数nの値が10になる。」

ソースコードについては各コードに番号を付け、下記のように修正しました。

1ページ目の修正個所は以上です。
引き続き、コメントなどでご意見を頂ければ幸いです。
ソースコード1

    int *n;    /* int型の値を表すポインタ変数nの宣言 */
    int n;     /* 一般の変数 n を宣言する場合 */
↓
    int n = 5;    /* 通常の変数 n の定義(初期値は5) */
    int *p = &n;  /* ポインタ変数pの定義(初期値はnのアドレス) */

ソースコード2

    #include 

    int main( void ) {
      int *n;
      *n = 5;   /* ポインタ変数nに値5を代入 */
      printf( "%d\n", *n );  /* ポインタ変数nが持つ値(5)の出力 */
      return 0;
    }
↓
    #include 

    int main( void ) {
      int n = 5;
      int *p = &n;
      *p = 10;   /* ポインタ変数を使って値10を代入 */
      printf( "%d\n", n );  /* 変数nの値を出力(10が表示される) */
      return 0;
    }
#16 mrkn   2008-04-03 23:21:37
そろそろ2ページ目が修正されても良い頃だと思うんですが,いったい何時になったら修正されるんですか?
まさか,このまま修正せず,この騒ぎが沈静化するのを待っているわけじゃないですよねぇ.
Google で「C/C++ ポインタ」などと検索すると,この記事がトップに出てきます.
それだけ影響力を持っているわけですから,責任持って修正もしくは削除されることを希望します.
#17 tomita   2008-04-04 14:04:11
builder編集部 冨田です。
4月4日 14時に本稿の2ページ目を修正しました。修正個所は下記の通りです。

見出し「ポインタ変数の特徴」の項

「 ポインタ変数には、一般の変数とは異なる以下のような特徴がある。これらについて順に説明していきたい。

1. 変数には複数の記述方法がある
2. 一般の変数からもアドレスを参照できる」

「 ポインタ変数には、一般の変数とは異なる以下のような特徴がある。これらについて順に説明していきたい。

1. ポインタ変数の宣言には変数名の前に*をつける
2. 一般の変数もアドレス演算子を利用してアドレスを参照できる」


見出し「1. 変数には複数の記述方法がある」

見出し「1. ポインタ変数の宣言には変数名の前に*をつける」の項目

「先ほどまで*nと記述してきたポインタ変数は、宣言以降はnという記述も許される。これが用いられるのは、たとえばキーボードなどから値を入力するときである。その例を以下に示す。」

「 *pと記述してポインタ変数を宣言すると、メモリ上にポインタ変数が確保される。pと記述した場合にはアドレス自体を指し、*pとした場合はアドレスが指し示す値を参照することになる。

※宣言だけではポインタ変数は初期化されず、どこのアドレスに格納されるのか不定。」

「 値が入力される前は、*nには値が設定されていない。しかしscanf()の後は*nに値が設定されている。このように、関数によって*nの値が変更されるときに、nのような記述が行われる。

 プログラム内で用いる値は*nでを示しているのだが、nが示しているのは、その値を記憶させるメモリ上のアドレスだ。それ自体は自動的に設定されるため、開発者が具体的なアドレスを設定する必要はない。

 しかし、プログラム内でscanf関数に値を入力してもらうときに、その値をどこに記憶させるのかはあらかじめ知らせておかなくてはならない。そこで、宣言時に具体的なアドレスが設定されているnを使って、入力された値の記憶場所を知らせているわけだ。

 つまり、*nはアドレスを介してプログラムで用いる値を参照していることになる。C/C++においては、このようにアドレスの値を用いることで、参照渡しのように機能させることができるようになっている。」

「 *pはポインタ変数pが指し示すアドレスにある値を示す。しかし、scanf関数で値を入力する際、どこに記憶させるのかは、あらかじめ知らせておかなくてはならない。そこで、宣言後に、変数nのアドレスをポインタ変数pに設定し、入力された値の記憶場所を知らせているわけだ。

 つまり、*nはアドレスを介してプログラムで用いる値を参照していることになる。C/C++においては、このようにアドレスの値を用いることで、JavaやVBにおける参照渡しのように機能させることができるようになっている。」


見出し「2. 一般の変数からもアドレスを参照できる」

見出し「2. 一般の変数もアドレス演算子を利用してアドレスを参照できる」の項

第1段落
「1.で示した例は、一般の変数を用いて記述することもできる。その例を以下に示す。」

「 1.で示した例は、一般の変数だけを用いて記述することもできる。その例を以下に示す。」

第2段落
「 値が入力される変数をint n;と宣言したときは、scanf( ..., &n );と記述している。この&nは、一般の変数nを用いて、その値が記憶されている場所(アドレス)を参照していることを表している。このときの&はアドレス演算子と呼ぶ。」

「 値が入力される変数をint n;と宣言したときは、scanf( ..., &n );と記述している。この&nは、一般の変数nを用いて、その値が記憶されている場所(アドレス)を参照していることを表している。このときの&をアドレス演算子と呼ぶ。」


ソースコードについてはコードに番号を付与し、下記のように修正しました。

2ページ目の修正個所は以上です。引き続き、本連載のレビューを進めてまいります。
読者の皆様には今後もコメントなどでご意見を頂ければ幸いです。
ソースコード3

    #include 

    int main( void ) {
      int *n;
      scanf( "%d", n );      /* *nの値をキーボードなどから入力(Enterで終了) */
      printf( "%d\n", *n );  /* nの値を出力 */
      return 0;
    }
↓
    #include 

    int main( void ) {
      int *p;
      int n = 0;
      p = &n;              /* ポインタ変数を変数mのアドレスで初期化 */

      printf( "%d\n", n);   /* 0が出力*/
      printf( "%d\n", *p);  /* 0が出力 */
      scanf( "%d", p );     /* キーボードなどから入力(Enterで終了) */
      printf( "%d\n", n);  /* 標準入力から入力された数値が出力される。*/
      printf( "%d\n", *p);  /* 標準入力から入力された数値が出力される。*/
      return 0;
    }
#18 しゃちょ   2008-04-04 15:42:14
勘違いや誤りは誰にもありますが、記事の品質確保の手段(例えばレビュー)は確保されているのでしょうか?そうした手段がないとしたら、他の記事についても内容に疑問符がついてしまいます。
また誤りのある記事をさらしたままにしたのも問題ではないでしょうか?Web運用のオペレーションを再考されたほうがよいと思います。

最後に筆者の方にアドバイスを『改訂第5版 ANSI C対応 はじめてのC』というよい本があるのでよく読んでくださいね。
#19 tomita   2008-04-04 20:02:21
Murakamiさん

builder編集部の冨田です。コメントありがとうございます。
ご指摘の通りです。修正しました。
#20 Murakami   2008-04-04 20:08:06
冨田さま。

操作ミスで私のコメントを消してしまいました。 流れが判らなくなってしまうといけないので
再掲いたします。

↓ここから↓
> ※宣言だけではポインタ変数は初期化されず、どこのアドレスに格納されるのか不定。

この部分ですが、

※宣言だけではポインタ変数は初期化されず、《どういった》アドレス《が》格納されるのか不定。

とするべきかと思います。
↑ここまで↑

失礼いたしました。 (_ _)
#21 Jitta   2008-04-08 22:52:05
2ページ目、ソースコード3の下、
「つまり、*nはアドレスを介して…」→「つまり、*pはアドレスを介して…」
単純だが重要なタイプミス。

「このようにアドレスの値を用いることで、JavaやVBにおける参照渡しのように機能させることができるようになっている。」→「このようにアドレスの値を用いることで、JavaやC#における参照型のように機能させることができる。」
値渡しの説明をしていないのに、参照渡しを出す必要はないでしょう?参照で十分ではないですか?
VB は、 ByRef や ByVal で参照渡しはイメージできるでしょうが、型を意識しない人が多いので、「参照型」の説明としては不適。

「※宣言だけではポインタ変数は初期化されず、どういったアドレスが格納されるのか不定。」→「変数の宣言をすると、その名前の変数が使えるようになる。しかし、ポインタ変数に限らず、最初にどんな値が入っているかは保証されていない。変数を宣言する場合は、必ず初期化してから使うようにする。」
今の書き方では、初期化されないのはポインタ変数だけのように思えます。また、これは C++ への渡し船としても働きますから(初期化されない値→初期化を保証する)、ポインタ変数に限らない方がいいと思います。
#22 επιστημη   2008-04-25 00:14:17
...で、いつまで「修正中」にしとくのかしら。
#23 taken   2008-07-03 12:27:02
いつのまにか、「修正中」が消えているようですが、記事は変わっていないようなので。
重箱の隅のようですみません。

「つまり、*nは」
 ↓
「つまり、*pは」

「/* ポインタ変数を変数mのアドレスで初期化 */」
 ↓
「/* ポインタ変数を変数nのアドレスで初期化 */」

過去の記事のコメントはチェックされているのでしょうか。
#24 tomita   2008-07-19 14:11:25
taken様

builder編集部 冨田です。いつもご愛読頂きありがとうございます。
また、以前からご指摘頂いていた点について、修正に反映できず
ご迷惑をおかけしました。

ご指摘の通りですので修正しました。

今後もご愛読頂けましたら幸いです。
2ページ目

ソースコード3
「/* ポインタ変数を変数mのアドレスで初期化 */」
 ↓
「/* ポインタ変数を変数nのアドレスで初期化 */」


「つまり、*nは」
 ↓
「つまり、*pは」
#25 かんさいあん   2008-08-20 12:31:02
確保!
#26 つー   2011-08-09 22:08:23
確かに初心者の方にとっては、混乱を招く説明ですが、
がんばって修正を行い、参考文献となるようにがんばってください
#27 炎上していると聞いて   2011-10-24 01:11:03
まぁ今いってもアレだけど、
どこの初心者だよと言いたい。
#28 一介の学生もどき   2011-12-07 22:51:40
ポインタのポインタ、俗に言うダブルポインタを使った関数間の受け渡し、さらにはポインタのみで配列を使わずに「入力した文字列をいつでも取り出せること」ができ、なおかつ読み込んだ文字列をポインタを使って関数間で自在に受け渡しができるレベルじゃないくせに、よく執筆しようと思いましたね。
最低このレベルが分かってないのにものを書こうと思うなんておこがましいです。勉強しなおしなさい。
  • 新着記事
  • 特集
  • ブログ